diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2012-11-09 12:15:52 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2012-11-09 12:16:06 +0100 |
commit | de4f791e30be4e4239b381c11745ffa4d87ddb8b (patch) | |
tree | 885e3a5d6670828b454cf676b4d42f78e28b1f0e /Source/JavaScriptCore/dfg | |
parent | b022df48697d40cdabdeafb2c29bb14fe489b6fe (diff) | |
download | qtwebkit-de4f791e30be4e4239b381c11745ffa4d87ddb8b.tar.gz |
Imported WebKit commit e2c32e2f53e02d388e70b9db88b91d8d9d28fc84 (http://svn.webkit.org/repository/webkit/trunk@133952)
Revert back to an older snapshot that should build on ARM
Diffstat (limited to 'Source/JavaScriptCore/dfg')
21 files changed, 388 insertions, 1646 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp index 02e578b29..e518c24a8 100644 --- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp +++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp @@ -159,7 +159,7 @@ void AbstractState::initialize(Graph& graph) } } -bool AbstractState::endBasicBlock(MergeMode mergeMode) +bool AbstractState::endBasicBlock(MergeMode mergeMode, BranchDirection* branchDirectionPtr) { ASSERT(m_block); @@ -167,7 +167,6 @@ bool AbstractState::endBasicBlock(MergeMode mergeMode) block->cfaFoundConstants = m_foundConstants; block->cfaDidFinish = m_isValid; - block->cfaBranchDirection = m_branchDirection; if (!m_isValid) { reset(); @@ -196,8 +195,12 @@ bool AbstractState::endBasicBlock(MergeMode mergeMode) ASSERT(mergeMode != DontMerge || !changed); + BranchDirection branchDirection = m_branchDirection; + if (branchDirectionPtr) + *branchDirectionPtr = branchDirection; + #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLog(" Branch direction = %s\n", branchDirectionToString(m_branchDirection)); + dataLog(" Branch direction = %s\n", branchDirectionToString(branchDirection)); #endif reset(); @@ -205,7 +208,7 @@ bool AbstractState::endBasicBlock(MergeMode mergeMode) if (mergeMode != MergeToSuccessors) return changed; - return mergeToSuccessors(m_graph, block); + return mergeToSuccessors(m_graph, block, branchDirection); } void AbstractState::reset() @@ -421,10 +424,7 @@ bool AbstractState::execute(unsigned indexInBlock) break; } speculateNumberUnary(node); - if (isInt32Speculation(forNode(node.child1()).m_type)) - forNode(nodeIndex).set(SpecDoubleReal); - else - forNode(nodeIndex).set(SpecDouble); + forNode(nodeIndex).set(SpecDouble); break; } @@ -448,13 +448,9 @@ bool AbstractState::execute(unsigned indexInBlock) forNode(nodeIndex).set(SpecInt32); break; } - if (Node::shouldSpeculateNumberExpectingDefined(m_graph[node.child1()], m_graph[node.child2()])) { + if (Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()])) { speculateNumberBinary(node); - if (isRealNumberSpeculation(forNode(node.child1()).m_type) - && isRealNumberSpeculation(forNode(node.child2()).m_type)) - forNode(nodeIndex).set(SpecDoubleReal); - else - forNode(nodeIndex).set(SpecDouble); + forNode(nodeIndex).set(SpecDouble); break; } if (node.op() == ValueAdd) { @@ -526,11 +522,7 @@ bool AbstractState::execute(unsigned indexInBlock) break; } speculateNumberBinary(node); - if (isRealNumberSpeculation(forNode(node.child1()).m_type) - || isRealNumberSpeculation(forNode(node.child2()).m_type)) - forNode(nodeIndex).set(SpecDoubleReal); - else - forNode(nodeIndex).set(SpecDouble); + forNode(nodeIndex).set(SpecDouble); break; } @@ -568,7 +560,7 @@ bool AbstractState::execute(unsigned indexInBlock) break; } } - if (Node::shouldSpeculateIntegerForArithmetic( + if (Node::shouldSpeculateInteger( m_graph[node.child1()], m_graph[node.child2()]) && node.canSpeculateInteger()) { speculateInt32Binary(node, true); // forcing can-exit, which is a bit on the conservative side. @@ -588,7 +580,7 @@ bool AbstractState::execute(unsigned indexInBlock) node.setCanExit(false); break; } - if (m_graph[node.child1()].shouldSpeculateIntegerForArithmetic() + if (m_graph[node.child1()].shouldSpeculateInteger() && node.canSpeculateInteger()) { speculateInt32Unary(node, true); forNode(nodeIndex).set(SpecInt32); @@ -613,22 +605,12 @@ bool AbstractState::execute(unsigned indexInBlock) } case LogicalNot: { - // First check if we can fold because the source is a constant. JSValue childConst = forNode(node.child1()).value(); if (childConst && trySetConstant(nodeIndex, jsBoolean(!childConst.toBoolean(m_codeBlock->globalObjectFor(node.codeOrigin)->globalExec())))) { m_foundConstants = true; node.setCanExit(false); break; } - // Next check if we can fold because we know that the source is an object or string and does not equal undefined. - if (isCellSpeculation(forNode(node.child1()).m_type) - && forNode(node.child1()).m_currentKnownStructure.hasSingleton() - && !forNode(node.child1()).m_currentKnownStructure.singleton()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node.codeOrigin)) - && trySetConstant(nodeIndex, jsBoolean(false))) { - m_foundConstants = true; - node.setCanExit(false); - break; - } Node& child = m_graph[node.child1()]; if (isBooleanSpeculation(child.prediction())) speculateBooleanUnary(node); @@ -696,13 +678,12 @@ bool AbstractState::execute(unsigned indexInBlock) case CompareGreater: case CompareGreaterEq: case CompareEq: { - bool constantWasSet = false; - JSValue leftConst = forNode(node.child1()).value(); JSValue rightConst = forNode(node.child2()).value(); if (leftConst && rightConst && leftConst.isNumber() && rightConst.isNumber()) { double a = leftConst.asNumber(); double b = rightConst.asNumber(); + bool constantWasSet; switch (node.op()) { case CompareLess: constantWasSet = trySetConstant(nodeIndex, jsBoolean(a < b)); @@ -724,20 +705,11 @@ bool AbstractState::execute(unsigned indexInBlock) constantWasSet = false; break; } - } - - if (!constantWasSet && node.op() == CompareEq) { - SpeculatedType leftType = forNode(node.child1()).m_type; - SpeculatedType rightType = forNode(node.child2()).m_type; - if ((isInt32Speculation(leftType) && isOtherSpeculation(rightType)) - || (isOtherSpeculation(leftType) && isInt32Speculation(rightType))) - constantWasSet = trySetConstant(nodeIndex, jsBoolean(false)); - } - - if (constantWasSet) { - m_foundConstants = true; - node.setCanExit(false); - break; + if (constantWasSet) { + m_foundConstants = true; + node.setCanExit(false); + break; + } } forNode(nodeIndex).set(SpecBoolean); @@ -870,7 +842,6 @@ bool AbstractState::execute(unsigned indexInBlock) switch (node.arrayMode().type()) { case Array::SelectUsingPredictions: case Array::Unprofiled: - case Array::Undecided: ASSERT_NOT_REACHED(); break; case Array::ForceExit: @@ -888,22 +859,6 @@ bool AbstractState::execute(unsigned indexInBlock) forNode(node.child2()).filter(SpecInt32); forNode(nodeIndex).makeTop(); break; - case Array::Int32: - forNode(node.child2()).filter(SpecInt32); - if (node.arrayMode().isOutOfBounds()) { - clobberWorld(node.codeOrigin, indexInBlock); - forNode(nodeIndex).makeTop(); - } else - forNode(nodeIndex).set(SpecInt32); - break; - case Array::Double: - forNode(node.child2()).filter(SpecInt32); - if (node.arrayMode().isOutOfBounds()) { - clobberWorld(node.codeOrigin, indexInBlock); - forNode(nodeIndex).makeTop(); - } else - forNode(nodeIndex).set(SpecDoubleReal); - break; case Array::Contiguous: case Array::ArrayStorage: case Array::SlowPutArrayStorage: @@ -971,20 +926,6 @@ bool AbstractState::execute(unsigned indexInBlock) case Array::Generic: clobberWorld(node.codeOrigin, indexInBlock); break; - case Array::Int32: - forNode(child1).filter(SpecCell); - forNode(child2).filter(SpecInt32); - forNode(child3).filter(SpecInt32); - if (node.arrayMode().isOutOfBounds()) - clobberWorld(node.codeOrigin, indexInBlock); - break; - case Array::Double: - forNode(child1).filter(SpecCell); - forNode(child2).filter(SpecInt32); - forNode(child3).filter(SpecRealNumber); - if (node.arrayMode().isOutOfBounds()) - clobberWorld(node.codeOrigin, indexInBlock); - break; case Array::Contiguous: case Array::ArrayStorage: forNode(child1).filter(SpecCell); @@ -1077,16 +1018,6 @@ bool AbstractState::execute(unsigned indexInBlock) case ArrayPush: node.setCanExit(true); - switch (node.arrayMode().type()) { - case Array::Int32: - forNode(node.child2()).filter(SpecInt32); - break; - case Array::Double: - forNode(node.child2()).filter(SpecRealNumber); - break; - default: - break; - } clobberWorld(node.codeOrigin, indexInBlock); forNode(nodeIndex).set(SpecNumber); break; @@ -1112,7 +1043,6 @@ bool AbstractState::execute(unsigned indexInBlock) break; case Branch: { - // First check if we can fold because the source is a constant. JSValue value = forNode(node.child1()).value(); if (value) { bool booleanValue = value.toBoolean(m_codeBlock->globalObjectFor(node.codeOrigin)->globalExec()); @@ -1123,14 +1053,6 @@ bool AbstractState::execute(unsigned indexInBlock) node.setCanExit(false); break; } - // Next check if we can fold because we know that the source is an object or string and does not equal undefined. - if (isCellSpeculation(forNode(node.child1()).m_type) - && forNode(node.child1()).m_currentKnownStructure.hasSingleton() - && !forNode(node.child1()).m_currentKnownStructure.singleton()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node.codeOrigin))) { - m_branchDirection = TakeTrue; - node.setCanExit(false); - break; - } // FIXME: The above handles the trivial cases of sparse conditional // constant propagation, but we can do better: // 1) If the abstract value does not have a concrete value but describes @@ -1200,13 +1122,13 @@ bool AbstractState::execute(unsigned indexInBlock) case NewArray: node.setCanExit(true); - forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructureForIndexingTypeDuringAllocation(node.indexingType())); + forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructure()); m_haveStructures = true; break; case NewArrayBuffer: node.setCanExit(true); - forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructureForIndexingTypeDuringAllocation(node.indexingType())); + forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructure()); m_haveStructures = true; break; @@ -1462,11 +1384,11 @@ bool AbstractState::execute(unsigned indexInBlock) case Array::String: forNode(node.child1()).filter(SpecString); break; - case Array::Int32: - case Array::Double: case Array::Contiguous: case Array::ArrayStorage: case Array::SlowPutArrayStorage: + // This doesn't filter anything meaningful right now. We may want to add + // CFA tracking of array mode speculations, but we don't have that, yet. forNode(node.child1()).filter(SpecCell); break; case Array::Arguments: @@ -1800,7 +1722,7 @@ inline bool AbstractState::merge(BasicBlock* from, BasicBlock* to) } inline bool AbstractState::mergeToSuccessors( - Graph& graph, BasicBlock* basicBlock) + Graph& graph, BasicBlock* basicBlock, BranchDirection branchDirection) { Node& terminal = graph[basicBlock->last()]; @@ -1808,7 +1730,7 @@ inline bool AbstractState::mergeToSuccessors( switch (terminal.op()) { case Jump: { - ASSERT(basicBlock->cfaBranchDirection == InvalidBranchDirection); + ASSERT(branchDirection == InvalidBranchDirection); #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLog(" Merging to block #%u.\n", terminal.takenBlockIndex()); #endif @@ -1816,17 +1738,17 @@ inline bool AbstractState::mergeToSuccessors( } case Branch: { - ASSERT(basicBlock->cfaBranchDirection != InvalidBranchDirection); + ASSERT(branchDirection != InvalidBranchDirection); bool changed = false; #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLog(" Merging to block #%u.\n", terminal.takenBlockIndex()); #endif - if (basicBlock->cfaBranchDirection != TakeFalse) + if (branchDirection != TakeFalse) changed |= merge(basicBlock, graph.m_blocks[terminal.takenBlockIndex()].get()); #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLog(" Merging to block #%u.\n", terminal.notTakenBlockIndex()); #endif - if (basicBlock->cfaBranchDirection != TakeTrue) + if (branchDirection != TakeTrue) changed |= merge(basicBlock, graph.m_blocks[terminal.notTakenBlockIndex()].get()); return changed; } @@ -1834,7 +1756,7 @@ inline bool AbstractState::mergeToSuccessors( case Return: case Throw: case ThrowReferenceError: - ASSERT(basicBlock->cfaBranchDirection == InvalidBranchDirection); + ASSERT(branchDirection == InvalidBranchDirection); return false; default: diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.h b/Source/JavaScriptCore/dfg/DFGAbstractState.h index 0e33140c0..ec1a06231 100644 --- a/Source/JavaScriptCore/dfg/DFGAbstractState.h +++ b/Source/JavaScriptCore/dfg/DFGAbstractState.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2011 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,7 +31,6 @@ #if ENABLE(DFG_JIT) #include "DFGAbstractValue.h" -#include "DFGBranchDirection.h" #include "DFGGraph.h" #include "DFGNode.h" #include <wtf/Vector.h> @@ -93,6 +92,36 @@ public: MergeToSuccessors }; + enum BranchDirection { + // This is not a branch and so there is no branch direction, or + // the branch direction has yet to be set. + InvalidBranchDirection, + + // The branch takes the true case. + TakeTrue, + + // The branch takes the false case. + TakeFalse, + + // For all we know, the branch could go either direction, so we + // have to assume the worst. + TakeBoth + }; + + static const char* branchDirectionToString(BranchDirection branchDirection) + { + switch (branchDirection) { + case InvalidBranchDirection: + return "Invalid"; + case TakeTrue: + return "TakeTrue"; + case TakeFalse: + return "TakeFalse"; + case TakeBoth: + return "TakeBoth"; + } + } + AbstractState(Graph&); ~AbstractState(); @@ -145,7 +174,11 @@ public: // A true return means that you must revisit (at least) the successor // blocks. This also sets cfaShouldRevisit to true for basic blocks // that must be visited next. - bool endBasicBlock(MergeMode); + // + // If you'd like to know what direction the branch at the end of the + // basic block is thought to have taken, you can pass a non-0 pointer + // for BranchDirection. + bool endBasicBlock(MergeMode, BranchDirection* = 0); // Reset the AbstractState. This throws away any results, and at this point // you can safely call beginBasicBlock() on any basic block. @@ -178,8 +211,8 @@ public: // successors. Returns true if any of the successors' states changed. Note // that this is automatically called in endBasicBlock() if MergeMode is // MergeToSuccessors. - bool mergeToSuccessors(Graph&, BasicBlock*); - + bool mergeToSuccessors(Graph&, BasicBlock*, BranchDirection); + void dump(FILE* out); private: diff --git a/Source/JavaScriptCore/dfg/DFGArrayMode.cpp b/Source/JavaScriptCore/dfg/DFGArrayMode.cpp index 0d15b9a30..699902a16 100644 --- a/Source/JavaScriptCore/dfg/DFGArrayMode.cpp +++ b/Source/JavaScriptCore/dfg/DFGArrayMode.cpp @@ -34,46 +34,19 @@ namespace JSC { namespace DFG { ArrayMode ArrayMode::fromObserved(ArrayProfile* profile, Array::Action action, bool makeSafe) { - ArrayModes observed = profile->observedArrayModes(); - switch (observed) { + switch (profile->observedArrayModes()) { case 0: return ArrayMode(Array::Unprofiled); case asArrayModes(NonArray): if (action == Array::Write && !profile->mayInterceptIndexedAccesses()) - return ArrayMode(Array::Undecided, Array::NonArray, Array::OutOfBounds, Array::Convert); + return ArrayMode(Array::Contiguous, Array::NonArray, Array::OutOfBounds, Array::Convert); // FIXME: we don't know whether to go to contiguous or array storage. We're making a static guess here. In future we should use exit profiling for this. return ArrayMode(Array::SelectUsingPredictions); - - case asArrayModes(ArrayWithUndecided): - if (action == Array::Write) - return ArrayMode(Array::Undecided, Array::Array, Array::OutOfBounds, Array::Convert); - return ArrayMode(Array::Generic); - - case asArrayModes(NonArray) | asArrayModes(ArrayWithUndecided): - if (action == Array::Write && !profile->mayInterceptIndexedAccesses()) - return ArrayMode(Array::Undecided, Array::PossiblyArray, Array::OutOfBounds, Array::Convert); - return ArrayMode(Array::SelectUsingPredictions); - - case asArrayModes(NonArrayWithInt32): - return ArrayMode(Array::Int32, Array::NonArray, Array::AsIs).withProfile(profile, makeSafe); - case asArrayModes(ArrayWithInt32): - return ArrayMode(Array::Int32, Array::Array, Array::AsIs).withProfile(profile, makeSafe); - case asArrayModes(NonArrayWithInt32) | asArrayModes(ArrayWithInt32): - return ArrayMode(Array::Int32, Array::PossiblyArray, Array::AsIs).withProfile(profile, makeSafe); - - case asArrayModes(NonArrayWithDouble): - return ArrayMode(Array::Double, Array::NonArray, Array::AsIs).withProfile(profile, makeSafe); - case asArrayModes(ArrayWithDouble): - return ArrayMode(Array::Double, Array::Array, Array::AsIs).withProfile(profile, makeSafe); - case asArrayModes(NonArrayWithDouble) | asArrayModes(ArrayWithDouble): - return ArrayMode(Array::Double, Array::PossiblyArray, Array::AsIs).withProfile(profile, makeSafe); - case asArrayModes(NonArrayWithContiguous): return ArrayMode(Array::Contiguous, Array::NonArray, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(ArrayWithContiguous): return ArrayMode(Array::Contiguous, Array::Array, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(NonArrayWithContiguous) | asArrayModes(ArrayWithContiguous): return ArrayMode(Array::Contiguous, Array::PossiblyArray, Array::AsIs).withProfile(profile, makeSafe); - case asArrayModes(NonArrayWithArrayStorage): return ArrayMode(Array::ArrayStorage, Array::NonArray, Array::AsIs).withProfile(profile, makeSafe); case asArrayModes(NonArrayWithSlowPutArrayStorage): @@ -89,39 +62,36 @@ ArrayMode ArrayMode::fromObserved(ArrayProfile* profile, Array::Action action, b case asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage): case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage): return ArrayMode(Array::SlowPutArrayStorage, Array::PossiblyArray, Array::AsIs).withProfile(profile, makeSafe); - + case asArrayModes(NonArrayWithContiguous) | asArrayModes(NonArrayWithArrayStorage): + return ArrayMode(Array::ArrayStorage, Array::NonArray, Array::Convert).withProfile(profile, makeSafe); + case asArrayModes(ArrayWithContiguous) | asArrayModes(ArrayWithArrayStorage): + return ArrayMode(Array::ArrayStorage, Array::Array, Array::Convert).withProfile(profile, makeSafe); + case asArrayModes(NonArrayWithContiguous) | asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithContiguous) | asArrayModes(ArrayWithArrayStorage): + return ArrayMode(Array::ArrayStorage, Array::PossiblyArray, Array::Convert).withProfile(profile, makeSafe); + case asArrayModes(NonArray) | asArrayModes(NonArrayWithContiguous): + if (action == Array::Write && !profile->mayInterceptIndexedAccesses()) + return ArrayMode(Array::Contiguous, Array::NonArray, Array::OutOfBounds, Array::Convert); + return ArrayMode(Array::SelectUsingPredictions); + case asArrayModes(NonArray) | asArrayModes(NonArrayWithContiguous) | asArrayModes(NonArrayWithArrayStorage): + case asArrayModes(NonArray) | asArrayModes(NonArrayWithArrayStorage): + if (action == Array::Write && !profile->mayInterceptIndexedAccesses()) + return ArrayMode(Array::ArrayStorage, Array::NonArray, Array::OutOfBounds, Array::Convert); + return ArrayMode(Array::SelectUsingPredictions); + case asArrayModes(NonArray) | asArrayModes(NonArrayWithSlowPutArrayStorage): + case asArrayModes(NonArray) | asArrayModes(NonArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage): + if (action == Array::Write && !profile->mayInterceptIndexedAccesses()) + return ArrayMode(Array::SlowPutArrayStorage, Array::NonArray, Array::OutOfBounds, Array::Convert); + return ArrayMode(Array::SelectUsingPredictions); default: - if ((observed & asArrayModes(NonArray)) && profile->mayInterceptIndexedAccesses()) - return ArrayMode(Array::SelectUsingPredictions); - - Array::Type type; - Array::Class arrayClass; - - if (shouldUseSlowPutArrayStorage(observed)) - type = Array::SlowPutArrayStorage; - else if (shouldUseFastArrayStorage(observed)) - type = Array::ArrayStorage; - else if (shouldUseContiguous(observed)) - type = Array::Contiguous; - else if (shouldUseDouble(observed)) - type = Array::Double; - else if (shouldUseInt32(observed)) - type = Array::Int32; - else - type = Array::Undecided; - - if (observed & (asArrayModes(ArrayWithUndecided) | asArrayModes(ArrayWithInt32) | asArrayModes(ArrayWithDouble) | asArrayModes(ArrayWithContiguous) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage))) - arrayClass = Array::Array; - else if (observed & (asArrayModes(NonArray) | asArrayModes(NonArrayWithInt32) | asArrayModes(NonArrayWithDouble) | asArrayModes(NonArrayWithContiguous) | asArrayModes(NonArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage))) - arrayClass = Array::NonArray; - else - arrayClass = Array::PossiblyArray; - - return ArrayMode(type, arrayClass, Array::Convert).withProfile(profile, makeSafe); + // We know that this is possibly a kind of array for which, though there is no + // useful data in the array profile, we may be able to extract useful data from + // the value profiles of the inputs. Hence, we leave it as undecided, and let + // the predictions propagator decide later. + return ArrayMode(Array::SelectUsingPredictions); } } -ArrayMode ArrayMode::refine(SpeculatedType base, SpeculatedType index, SpeculatedType value) const +ArrayMode ArrayMode::refine(SpeculatedType base, SpeculatedType index) const { if (!base || !index) { // It can be that we had a legitimate arrayMode but no incoming predictions. That'll @@ -134,85 +104,49 @@ ArrayMode ArrayMode::refine(SpeculatedType base, SpeculatedType index, Speculate if (!isInt32Speculation(index) || !isCellSpeculation(base)) return ArrayMode(Array::Generic); - switch (type()) { - case Array::Unprofiled: + if (type() == Array::Unprofiled) { + // If the indexing type wasn't recorded in the array profile but the values are + // base=cell property=int, then we know that this access didn't execute. return ArrayMode(Array::ForceExit); - - case Array::Undecided: - if (!value) - return withType(Array::ForceExit); - if (isInt32Speculation(value)) - return withTypeAndConversion(Array::Int32, Array::Convert); - if (isNumberSpeculation(value)) - return withTypeAndConversion(Array::Double, Array::Convert); - return withTypeAndConversion(Array::Contiguous, Array::Convert); - - case Array::Int32: - if (!value || isInt32Speculation(value)) - return *this; - if (isNumberSpeculation(value)) - return withTypeAndConversion(Array::Double, Array::Convert); - return withTypeAndConversion(Array::Contiguous, Array::Convert); - - case Array::Double: - if (!value || isNumberSpeculation(value)) - return *this; - return withTypeAndConversion(Array::Contiguous, Array::Convert); - - case Array::SelectUsingPredictions: - if (isStringSpeculation(base)) - return ArrayMode(Array::String); - - if (isArgumentsSpeculation(base)) - return ArrayMode(Array::Arguments); - - if (isInt8ArraySpeculation(base)) - return ArrayMode(Array::Int8Array); - - if (isInt16ArraySpeculation(base)) - return ArrayMode(Array::Int16Array); - - if (isInt32ArraySpeculation(base)) - return ArrayMode(Array::Int32Array); - - if (isUint8ArraySpeculation(base)) - return ArrayMode(Array::Uint8Array); - - if (isUint8ClampedArraySpeculation(base)) - return ArrayMode(Array::Uint8ClampedArray); - - if (isUint16ArraySpeculation(base)) - return ArrayMode(Array::Uint16Array); - - if (isUint32ArraySpeculation(base)) - return ArrayMode(Array::Uint32Array); - - if (isFloat32ArraySpeculation(base)) - return ArrayMode(Array::Float32Array); - - if (isFloat64ArraySpeculation(base)) - return ArrayMode(Array::Float64Array); - - return ArrayMode(Array::Generic); - - default: - return *this; - } -} - -bool ArrayMode::alreadyChecked(AbstractValue& value, IndexingType shape) const -{ - if (isJSArray()) { - if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(shape | IsArray))) - return true; - return value.m_currentKnownStructure.hasSingleton() - && (value.m_currentKnownStructure.singleton()->indexingType() & IndexingShapeMask) == shape - && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray); } - if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(shape) | asArrayModes(shape | IsArray))) - return true; - return value.m_currentKnownStructure.hasSingleton() - && (value.m_currentKnownStructure.singleton()->indexingType() & IndexingShapeMask) == shape; + + if (type() != Array::SelectUsingPredictions) + return *this; + + if (isStringSpeculation(base)) + return ArrayMode(Array::String); + + if (isArgumentsSpeculation(base)) + return ArrayMode(Array::Arguments); + + if (isInt8ArraySpeculation(base)) + return ArrayMode(Array::Int8Array); + + if (isInt16ArraySpeculation(base)) + return ArrayMode(Array::Int16Array); + + if (isInt32ArraySpeculation(base)) + return ArrayMode(Array::Int32Array); + + if (isUint8ArraySpeculation(base)) + return ArrayMode(Array::Uint8Array); + + if (isUint8ClampedArraySpeculation(base)) + return ArrayMode(Array::Uint8ClampedArray); + + if (isUint16ArraySpeculation(base)) + return ArrayMode(Array::Uint16Array); + + if (isUint32ArraySpeculation(base)) + return ArrayMode(Array::Uint32Array); + + if (isFloat32ArraySpeculation(base)) + return ArrayMode(Array::Float32Array); + + if (isFloat64ArraySpeculation(base)) + return ArrayMode(Array::Float64Array); + + return ArrayMode(Array::Generic); } bool ArrayMode::alreadyChecked(AbstractValue& value) const @@ -227,17 +161,31 @@ bool ArrayMode::alreadyChecked(AbstractValue& value) const case Array::String: return speculationChecked(value.m_type, SpecString); - case Array::Int32: - return alreadyChecked(value, Int32Shape); - - case Array::Double: - return alreadyChecked(value, DoubleShape); - case Array::Contiguous: - return alreadyChecked(value, ContiguousShape); + if (isJSArray()) { + if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(ArrayWithContiguous))) + return true; + return value.m_currentKnownStructure.hasSingleton() + && hasContiguous(value.m_currentKnownStructure.singleton()->indexingType()) + && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray); + } + if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(NonArrayWithContiguous) | asArrayModes(ArrayWithContiguous))) + return true; + return value.m_currentKnownStructure.hasSingleton() + && hasContiguous(value.m_currentKnownStructure.singleton()->indexingType()); case Array::ArrayStorage: - return alreadyChecked(value, ArrayStorageShape); + if (isJSArray()) { + if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(ArrayWithArrayStorage))) + return true; + return value.m_currentKnownStructure.hasSingleton() + && hasFastArrayStorage(value.m_currentKnownStructure.singleton()->indexingType()) + && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray); + } + if (arrayModesAlreadyChecked(value.m_arrayModes, asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage))) + return true; + return value.m_currentKnownStructure.hasSingleton() + && hasFastArrayStorage(value.m_currentKnownStructure.singleton()->indexingType()); case Array::SlowPutArrayStorage: if (isJSArray()) { @@ -284,7 +232,6 @@ bool ArrayMode::alreadyChecked(AbstractValue& value) const case Array::SelectUsingPredictions: case Array::Unprofiled: - case Array::Undecided: break; } @@ -305,12 +252,6 @@ const char* arrayTypeToString(Array::Type type) return "ForceExit"; case Array::String: return "String"; - case Array::Undecided: - return "Undecided"; - case Array::Int32: - return "Int32"; - case Array::Double: - return "Double"; case Array::Contiguous: return "Contiguous"; case Array::ArrayStorage: diff --git a/Source/JavaScriptCore/dfg/DFGArrayMode.h b/Source/JavaScriptCore/dfg/DFGArrayMode.h index 206d689f2..615965c92 100644 --- a/Source/JavaScriptCore/dfg/DFGArrayMode.h +++ b/Source/JavaScriptCore/dfg/DFGArrayMode.h @@ -52,10 +52,7 @@ enum Type { ForceExit, // Implies that we have no idea how to execute this operation, so we should just give up. Generic, String, - - Undecided, - Int32, - Double, + Contiguous, ArrayStorage, SlowPutArrayStorage, @@ -84,6 +81,7 @@ enum Speculation { ToHole, OutOfBounds }; + enum Conversion { AsIs, Convert @@ -171,17 +169,7 @@ public: return ArrayMode(type(), myArrayClass, mySpeculation, conversion()); } - ArrayMode withType(Array::Type type) const - { - return ArrayMode(type, arrayClass(), speculation(), conversion()); - } - - ArrayMode withTypeAndConversion(Array::Type type, Array::Conversion conversion) const - { - return ArrayMode(type, arrayClass(), speculation(), conversion); - } - - ArrayMode refine(SpeculatedType base, SpeculatedType index, SpeculatedType value = SpecNone) const; + ArrayMode refine(SpeculatedType base, SpeculatedType index) const; bool alreadyChecked(AbstractValue&) const; @@ -190,8 +178,6 @@ public: bool usesButterfly() const { switch (type()) { - case Array::Int32: - case Array::Double: case Array::Contiguous: case Array::ArrayStorage: case Array::SlowPutArrayStorage: @@ -277,7 +263,6 @@ public: case Array::Unprofiled: case Array::ForceExit: case Array::Generic: - case Array::Undecided: return false; default: return true; @@ -292,8 +277,6 @@ public: case Array::ForceExit: case Array::Generic: return false; - case Array::Int32: - case Array::Double: case Array::Contiguous: case Array::ArrayStorage: case Array::SlowPutArrayStorage: @@ -326,10 +309,6 @@ public: switch (type()) { case Array::Generic: return ALL_ARRAY_MODES; - case Array::Int32: - return arrayModesWithIndexingShape(Int32Shape); - case Array::Double: - return arrayModesWithIndexingShape(DoubleShape); case Array::Contiguous: return arrayModesWithIndexingShape(ContiguousShape); case Array::ArrayStorage: @@ -375,8 +354,6 @@ private: } } - bool alreadyChecked(AbstractValue&, IndexingType shape) const; - union { struct { uint8_t type; diff --git a/Source/JavaScriptCore/dfg/DFGBasicBlock.h b/Source/JavaScriptCore/dfg/DFGBasicBlock.h index 6f348f2e1..441e2e75e 100644 --- a/Source/JavaScriptCore/dfg/DFGBasicBlock.h +++ b/Source/JavaScriptCore/dfg/DFGBasicBlock.h @@ -29,7 +29,6 @@ #if ENABLE(DFG_JIT) #include "DFGAbstractValue.h" -#include "DFGBranchDirection.h" #include "DFGNode.h" #include "Operands.h" #include <wtf/OwnPtr.h> @@ -47,7 +46,6 @@ struct BasicBlock : Vector<NodeIndex, 8> { , cfaShouldRevisit(false) , cfaFoundConstants(false) , cfaDidFinish(true) - , cfaBranchDirection(InvalidBranchDirection) #if !ASSERT_DISABLED , isLinked(false) #endif @@ -107,7 +105,6 @@ struct BasicBlock : Vector<NodeIndex, 8> { bool cfaShouldRevisit; bool cfaFoundConstants; bool cfaDidFinish; - BranchDirection cfaBranchDirection; #if !ASSERT_DISABLED bool isLinked; #endif diff --git a/Source/JavaScriptCore/dfg/DFGBranchDirection.h b/Source/JavaScriptCore/dfg/DFGBranchDirection.h deleted file mode 100644 index 8bbe3c635..000000000 --- a/Source/JavaScriptCore/dfg/DFGBranchDirection.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2012 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef DFGBranchDirection_h -#define DFGBranchDirection_h - -#include <wtf/Platform.h> - -#if ENABLE(DFG_JIT) - -namespace JSC { namespace DFG { - -enum BranchDirection { - // This is not a branch and so there is no branch direction, or - // the branch direction has yet to be set. - InvalidBranchDirection, - - // The branch takes the true case. - TakeTrue, - - // The branch takes the false case. - TakeFalse, - - // For all we know, the branch could go either direction, so we - // have to assume the worst. - TakeBoth -}; - -static inline const char* branchDirectionToString(BranchDirection branchDirection) -{ - switch (branchDirection) { - case InvalidBranchDirection: - return "Invalid"; - case TakeTrue: - return "TakeTrue"; - case TakeFalse: - return "TakeFalse"; - case TakeBoth: - return "TakeBoth"; - } -} - -static inline bool isKnownDirection(BranchDirection branchDirection) -{ - switch (branchDirection) { - case TakeTrue: - case TakeFalse: - return true; - default: - return false; - } -} - -static inline bool branchCondition(BranchDirection branchDirection) -{ - if (branchDirection == TakeTrue) - return true; - ASSERT(branchDirection == TakeFalse); - return false; -} - -} } // namespace JSC::DFG - -#endif // ENABLE(DFG_JIT) - -#endif // DFGBranchDirection_h diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp index 142b8ab95..70aa2b637 100644 --- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp +++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp @@ -905,15 +905,10 @@ private: return getPrediction(m_graph.size(), m_currentProfilingIndex); } - ArrayMode getArrayMode(ArrayProfile* profile, Array::Action action) - { - profile->computeUpdatedPrediction(m_inlineStackTop->m_codeBlock); - return ArrayMode::fromObserved(profile, action, false); - } - ArrayMode getArrayMode(ArrayProfile* profile) { - return getArrayMode(profile, Array::Read); + profile->computeUpdatedPrediction(m_inlineStackTop->m_codeBlock); + return ArrayMode::fromObserved(profile, Array::Read, false); } ArrayMode getArrayModeAndEmitChecks(ArrayProfile* profile, Array::Action action, NodeIndex base) @@ -1654,12 +1649,7 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins return false; ArrayMode arrayMode = getArrayMode(m_currentInstruction[5].u.arrayProfile); - if (!arrayMode.isJSArray()) - return false; switch (arrayMode.type()) { - case Array::Undecided: - case Array::Int32: - case Array::Double: case Array::Contiguous: case Array::ArrayStorage: { NodeIndex arrayPush = addToGraph(ArrayPush, OpInfo(arrayMode.asWord()), OpInfo(prediction), get(registerOffset + argumentToOperand(0)), get(registerOffset + argumentToOperand(1))); @@ -1679,11 +1669,7 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins return false; ArrayMode arrayMode = getArrayMode(m_currentInstruction[5].u.arrayProfile); - if (!arrayMode.isJSArray()) - return false; switch (arrayMode.type()) { - case Array::Int32: - case Array::Double: case Array::Contiguous: case Array::ArrayStorage: { NodeIndex arrayPop = addToGraph(ArrayPop, OpInfo(arrayMode.asWord()), OpInfo(prediction), get(registerOffset + argumentToOperand(0))); @@ -1768,7 +1754,7 @@ bool ByteCodeParser::handleConstantInternalFunction( if (argumentCountIncludingThis == 2) { setIntrinsicResult( usesResult, resultOperand, - addToGraph(NewArrayWithSize, OpInfo(ArrayWithUndecided), get(registerOffset + argumentToOperand(1)))); + addToGraph(NewArrayWithSize, get(registerOffset + argumentToOperand(1)))); return true; } @@ -1776,7 +1762,7 @@ bool ByteCodeParser::handleConstantInternalFunction( addVarArgChild(get(registerOffset + argumentToOperand(i))); setIntrinsicResult( usesResult, resultOperand, - addToGraph(Node::VarArg, NewArray, OpInfo(ArrayWithUndecided), OpInfo(0))); + addToGraph(Node::VarArg, NewArray, OpInfo(0), OpInfo(0))); return true; } @@ -2136,37 +2122,24 @@ bool ByteCodeParser::parseBlock(unsigned limit) case op_new_array: { int startOperand = currentInstruction[2].u.operand; int numOperands = currentInstruction[3].u.operand; - ArrayAllocationProfile* profile = currentInstruction[4].u.arrayAllocationProfile; for (int operandIdx = startOperand; operandIdx < startOperand + numOperands; ++operandIdx) addVarArgChild(get(operandIdx)); - set(currentInstruction[1].u.operand, addToGraph(Node::VarArg, NewArray, OpInfo(profile->selectIndexingType()), OpInfo(0))); + set(currentInstruction[1].u.operand, addToGraph(Node::VarArg, NewArray, OpInfo(0), OpInfo(0))); NEXT_OPCODE(op_new_array); } case op_new_array_with_size: { int lengthOperand = currentInstruction[2].u.operand; - ArrayAllocationProfile* profile = currentInstruction[3].u.arrayAllocationProfile; - set(currentInstruction[1].u.operand, addToGraph(NewArrayWithSize, OpInfo(profile->selectIndexingType()), get(lengthOperand))); + set(currentInstruction[1].u.operand, addToGraph(NewArrayWithSize, get(lengthOperand))); NEXT_OPCODE(op_new_array_with_size); } case op_new_array_buffer: { int startConstant = currentInstruction[2].u.operand; int numConstants = currentInstruction[3].u.operand; - ArrayAllocationProfile* profile = currentInstruction[4].u.arrayAllocationProfile; NewArrayBufferData data; data.startConstant = m_inlineStackTop->m_constantBufferRemap[startConstant]; data.numConstants = numConstants; - data.indexingType = profile->selectIndexingType(); - - // If this statement has never executed, we'll have the wrong indexing type in the profile. - for (int i = 0; i < numConstants; ++i) { - data.indexingType = - leastUpperBoundOfIndexingTypeAndValue( - data.indexingType, - m_codeBlock->constantBuffer(data.startConstant)[i]); - } - m_graph.m_newArrayBufferData.append(data); set(currentInstruction[1].u.operand, addToGraph(NewArrayBuffer, OpInfo(&m_graph.m_newArrayBufferData.last()))); NEXT_OPCODE(op_new_array_buffer); diff --git a/Source/JavaScriptCore/dfg/DFGCCallHelpers.h b/Source/JavaScriptCore/dfg/DFGCCallHelpers.h index 308dde5a6..a2570b7ea 100644 --- a/Source/JavaScriptCore/dfg/DFGCCallHelpers.h +++ b/Source/JavaScriptCore/dfg/DFGCCallHelpers.h @@ -210,15 +210,6 @@ public: addCallArgument(arg3); } - ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, GPRReg arg3) - { - resetCallArguments(); - addCallArgument(GPRInfo::callFrameRegister); - addCallArgument(arg1); - addCallArgument(arg2); - addCallArgument(arg3); - } - ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImmPtr arg3) { resetCallArguments(); @@ -277,16 +268,6 @@ public: addCallArgument(arg4); } - ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImm32 arg4) - { - resetCallArguments(); - addCallArgument(GPRInfo::callFrameRegister); - addCallArgument(arg1); - addCallArgument(arg2); - addCallArgument(arg3); - addCallArgument(arg4); - } - ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImmPtr arg2, GPRReg arg3) { resetCallArguments(); @@ -336,23 +317,6 @@ public: addCallArgument(arg4); addCallArgument(arg5); } - - ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, GPRReg arg2) - { - resetCallArguments(); - addCallArgument(GPRInfo::callFrameRegister); - addCallArgument(arg1); - addCallArgument(arg2); - } - - ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, FPRReg arg3) - { - resetCallArguments(); - addCallArgument(GPRInfo::callFrameRegister); - addCallArgument(arg1); - addCallArgument(arg2); - addCallArgument(arg3); - } #endif // !NUMBER_OF_ARGUMENT_REGISTERS // These methods are suitable for any calling convention that provides for // at least 4 argument registers, e.g. X86_64, ARMv7. @@ -499,20 +463,6 @@ public: { setupTwoStubArgs<FPRInfo::argumentFPR0, FPRInfo::argumentFPR1>(arg1, arg2); } - - ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, GPRReg arg2) - { - moveDouble(arg1, FPRInfo::argumentFPR0); - move(arg2, GPRInfo::argumentGPR1); - move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); - } - - ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, FPRReg arg3) - { - moveDouble(arg3, FPRInfo::argumentFPR0); - setupStubArguments(arg1, arg2); - move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); - } #elif CPU(ARM) #if CPU(ARM_HARDFP) ALWAYS_INLINE void setupArguments(FPRReg arg1) @@ -546,21 +496,6 @@ public: assembler().vmov(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, arg1); assembler().vmov(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3, arg2); } - - ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, GPRReg arg2) - { - move(arg2, GPRInfo::argumentGPR3); - assembler().vmov(GPRInfo::argumentGPR1, GPRInfo::argumentGPR2, arg1); - move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); - } - - ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, FPRReg arg3) - { - setupStubArguments(arg1, arg2); - move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); - assembler().vmov(GPRInfo::argumentGPR3, GPRInfo::nonArgGPR0, arg3); - poke(GPRInfo::nonArgGPR0); - } #endif // CPU(ARM_HARDFP) #else #error "DFG JIT not supported on this platform." @@ -700,13 +635,6 @@ public: move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); } - ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, GPRReg arg3) - { - setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR3>(arg1, arg3); - move(arg2, GPRInfo::argumentGPR2); - move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); - } - ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImmPtr arg3) { move(arg1, GPRInfo::argumentGPR1); @@ -795,12 +723,6 @@ public: setupArgumentsWithExecState(arg1, arg2, arg3); } - ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImm32 arg4) - { - poke(arg4); - setupArgumentsWithExecState(arg1, arg2, arg3); - } - ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImm32 arg3, GPRReg arg4) { poke(arg4); diff --git a/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp b/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp index e3827d8ad..e0d973992 100644 --- a/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp @@ -99,8 +99,9 @@ public: case Branch: { // Branch on constant -> jettison the not-taken block and merge. - if (isKnownDirection(block->cfaBranchDirection)) { - bool condition = branchCondition(block->cfaBranchDirection); + if (m_graph[m_graph[block->last()].child1()].hasConstant()) { + bool condition = + m_graph.valueOfJSConstant(m_graph[block->last()].child1().index()).toBoolean(m_graph.globalObjectFor(m_graph[block->last()].codeOrigin)->globalExec()); BasicBlock* targetBlock = m_graph.m_blocks[ m_graph.successorForCondition(block, condition)].get(); if (targetBlock->m_predecessors.size() == 1) { @@ -729,7 +730,6 @@ private: } firstBlock->valuesAtTail = secondBlock->valuesAtTail; - firstBlock->cfaBranchDirection = secondBlock->cfaBranchDirection; m_graph.m_blocks[secondBlockIndex].clear(); } diff --git a/Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h b/Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h index 03713b6c5..46d5f44cb 100644 --- a/Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h +++ b/Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h @@ -61,7 +61,7 @@ protected: jit->silentSpill(m_plans[i]); jit->callOperation(m_function, m_resultGPR, m_structure, m_size); GPRReg canTrample = SpeculativeJIT::pickCanTrample(m_resultGPR); - for (unsigned i = m_plans.size(); i--;) + for (unsigned i = 0; i < m_plans.size(); ++i) jit->silentFill(m_plans[i], canTrample); jit->m_jit.loadPtr(MacroAssembler::Address(m_resultGPR, JSObject::butterflyOffset()), m_storageGPR); jumpTo(jit); @@ -106,7 +106,7 @@ protected: done.link(&jit->m_jit); jit->callOperation(m_function, m_resultGPR, scratchGPR, m_sizeGPR); GPRReg canTrample = SpeculativeJIT::pickCanTrample(m_resultGPR); - for (unsigned i = m_plans.size(); i--;) + for (unsigned i = 0; i < m_plans.size(); ++i) jit->silentFill(m_plans[i], canTrample); jumpTo(jit); } diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp index 621d6e96a..5a76aa8df 100644 --- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp @@ -145,30 +145,7 @@ private: } case ArrayPush: { - // May need to refine the array mode in case the value prediction contravenes - // the array prediction. For example, we may have evidence showing that the - // array is in Int32 mode, but the value we're storing is likely to be a double. - // Then we should turn this into a conversion to Double array followed by the - // push. On the other hand, we absolutely don't want to refine based on the - // base prediction. If it has non-cell garbage in it, then we want that to be - // ignored. That's because ArrayPush can't handle any array modes that aren't - // array-related - so if refine() turned this into a "Generic" ArrayPush then - // that would break things. - node.setArrayMode( - node.arrayMode().refine( - m_graph[node.child1()].prediction() & SpecCell, - SpecInt32, - m_graph[node.child2()].prediction())); blessArrayOperation(node.child1(), node.child2(), 2); - - Node* nodePtr = &m_graph[m_compileIndex]; - switch (nodePtr->arrayMode().type()) { - case Array::Double: - fixDoubleEdge(1); - break; - default: - break; - } break; } @@ -259,7 +236,7 @@ private: case ValueAdd: { if (m_graph.addShouldSpeculateInteger(node)) break; - if (!Node::shouldSpeculateNumberExpectingDefined(m_graph[node.child1()], m_graph[node.child2()])) + if (!Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()])) break; fixDoubleEdge(0); fixDoubleEdge(1); @@ -285,7 +262,7 @@ private: case ArithMin: case ArithMax: case ArithMod: { - if (Node::shouldSpeculateIntegerForArithmetic(m_graph[node.child1()], m_graph[node.child2()]) + if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()]) && node.canSpeculateInteger()) break; fixDoubleEdge(0); @@ -302,7 +279,7 @@ private: } case ArithDiv: { - if (Node::shouldSpeculateIntegerForArithmetic(m_graph[node.child1()], m_graph[node.child2()]) + if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()]) && node.canSpeculateInteger()) { if (isX86()) break; @@ -330,7 +307,7 @@ private: } case ArithAbs: { - if (m_graph[node.child1()].shouldSpeculateIntegerForArithmetic() + if (m_graph[node.child1()].shouldSpeculateInteger() && node.canSpeculateInteger()) break; fixDoubleEdge(0); @@ -351,17 +328,13 @@ private: node.setArrayMode( node.arrayMode().refine( m_graph[child1].prediction(), - m_graph[child2].prediction(), - m_graph[child3].prediction())); + m_graph[child2].prediction())); blessArrayOperation(child1, child2, 3); Node* nodePtr = &m_graph[m_compileIndex]; switch (nodePtr->arrayMode().modeForPut().type()) { - case Array::Double: - fixDoubleEdge(2); - break; case Array::Int8Array: case Array::Int16Array: case Array::Int32Array: @@ -382,19 +355,6 @@ private: break; } - case NewArray: { - for (unsigned i = m_graph.varArgNumChildren(node); i--;) { - node.setIndexingType( - leastUpperBoundOfIndexingTypeAndType( - node.indexingType(), m_graph[m_graph.varArgChild(node, i)].prediction())); - } - if (node.indexingType() == ArrayWithDouble) { - for (unsigned i = m_graph.varArgNumChildren(node); i--;) - fixDoubleEdge(i); - } - break; - } - default: break; } @@ -432,17 +392,15 @@ private: if (arrayMode.isJSArrayWithOriginalStructure()) { JSGlobalObject* globalObject = m_graph.baselineCodeBlockFor(codeOrigin)->globalObject(); switch (arrayMode.type()) { - case Array::Int32: - structure = globalObject->originalArrayStructureForIndexingType(ArrayWithInt32); - break; - case Array::Double: - structure = globalObject->originalArrayStructureForIndexingType(ArrayWithDouble); - break; case Array::Contiguous: - structure = globalObject->originalArrayStructureForIndexingType(ArrayWithContiguous); + structure = globalObject->arrayStructure(); + if (structure->indexingType() != ArrayWithContiguous) + structure = 0; break; case Array::ArrayStorage: - structure = globalObject->originalArrayStructureForIndexingType(ArrayWithArrayStorage); + structure = globalObject->arrayStructureWithArrayStorage(); + if (structure->indexingType() != ArrayWithArrayStorage) + structure = 0; break; default: break; diff --git a/Source/JavaScriptCore/dfg/DFGGraph.cpp b/Source/JavaScriptCore/dfg/DFGGraph.cpp index 38079f020..8e8817f81 100644 --- a/Source/JavaScriptCore/dfg/DFGGraph.cpp +++ b/Source/JavaScriptCore/dfg/DFGGraph.cpp @@ -287,11 +287,6 @@ void Graph::dump(const char* prefix, NodeIndex nodeIndex) dataLog("]"); hasPrinted = true; } - if (node.hasIndexingType()) { - if (hasPrinted) - dataLog(", "); - dataLog("%s", indexingTypeToString(node.indexingType())); - } if (op == JSConstant) { dataLog("%s$%u", hasPrinted ? ", " : "", node.constantNumber()); JSValue value = valueOfJSConstant(nodeIndex); diff --git a/Source/JavaScriptCore/dfg/DFGGraph.h b/Source/JavaScriptCore/dfg/DFGGraph.h index 4de2e0e26..9fbb2df07 100644 --- a/Source/JavaScriptCore/dfg/DFGGraph.h +++ b/Source/JavaScriptCore/dfg/DFGGraph.h @@ -220,7 +220,7 @@ public: if (right.hasConstant()) return addImmediateShouldSpeculateInteger(add, left, right); - return Node::shouldSpeculateIntegerExpectingDefined(left, right) && add.canSpeculateInteger(); + return Node::shouldSpeculateInteger(left, right) && add.canSpeculateInteger(); } bool mulShouldSpeculateInteger(Node& mul) @@ -235,13 +235,13 @@ public: if (right.hasConstant()) return mulImmediateShouldSpeculateInteger(mul, left, right); - return Node::shouldSpeculateIntegerForArithmetic(left, right) && mul.canSpeculateInteger() && !nodeMayOverflow(mul.arithNodeFlags()); + return Node::shouldSpeculateInteger(left, right) && mul.canSpeculateInteger() && !nodeMayOverflow(mul.arithNodeFlags()); } bool negateShouldSpeculateInteger(Node& negate) { ASSERT(negate.op() == ArithNegate); - return at(negate.child1()).shouldSpeculateIntegerForArithmetic() && negate.canSpeculateInteger(); + return at(negate.child1()).shouldSpeculateInteger() && negate.canSpeculateInteger(); } bool addShouldSpeculateInteger(NodeIndex nodeIndex) @@ -493,8 +493,6 @@ public: switch (node.arrayMode().type()) { case Array::Generic: return false; - case Array::Int32: - case Array::Double: case Array::Contiguous: case Array::ArrayStorage: return !node.arrayMode().isOutOfBounds(); @@ -714,7 +712,7 @@ private: if (!immediateValue.isNumber()) return false; - if (!variable.shouldSpeculateIntegerExpectingDefined()) + if (!variable.shouldSpeculateInteger()) return false; if (immediateValue.isInt32()) @@ -736,7 +734,7 @@ private: if (!immediateValue.isInt32()) return false; - if (!variable.shouldSpeculateIntegerForArithmetic()) + if (!variable.shouldSpeculateInteger()) return false; int32_t intImmediate = immediateValue.asInt32(); diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h index bff7fe65f..e66629ec4 100644 --- a/Source/JavaScriptCore/dfg/DFGNode.h +++ b/Source/JavaScriptCore/dfg/DFGNode.h @@ -62,7 +62,6 @@ struct StructureTransitionData { struct NewArrayBufferData { unsigned startConstant; unsigned numConstants; - IndexingType indexingType; }; // This type used in passing an immediate argument to Node constructor; @@ -434,32 +433,6 @@ struct Node { return newArrayBufferData()->numConstants; } - bool hasIndexingType() - { - switch (op()) { - case NewArray: - case NewArrayWithSize: - case NewArrayBuffer: - return true; - default: - return false; - } - } - - IndexingType indexingType() - { - ASSERT(hasIndexingType()); - if (op() == NewArrayBuffer) - return newArrayBufferData()->indexingType; - return m_opInfo; - } - - void setIndexingType(IndexingType indexingType) - { - ASSERT(hasIndexingType()); - m_opInfo = indexingType; - } - bool hasRegexpIndex() { return op() == NewRegexp; @@ -949,36 +922,16 @@ struct Node { return isInt32Speculation(prediction()); } - bool shouldSpeculateIntegerForArithmetic() - { - return isInt32SpeculationForArithmetic(prediction()); - } - - bool shouldSpeculateIntegerExpectingDefined() - { - return isInt32SpeculationExpectingDefined(prediction()); - } - bool shouldSpeculateDouble() { return isDoubleSpeculation(prediction()); } - bool shouldSpeculateDoubleForArithmetic() - { - return isDoubleSpeculationForArithmetic(prediction()); - } - bool shouldSpeculateNumber() { return isNumberSpeculation(prediction()); } - bool shouldSpeculateNumberExpectingDefined() - { - return isNumberSpeculationExpectingDefined(prediction()); - } - bool shouldSpeculateBoolean() { return isBooleanSpeculation(prediction()); @@ -1084,31 +1037,11 @@ struct Node { return op1.shouldSpeculateInteger() && op2.shouldSpeculateInteger(); } - static bool shouldSpeculateIntegerForArithmetic(Node& op1, Node& op2) - { - return op1.shouldSpeculateIntegerForArithmetic() && op2.shouldSpeculateIntegerForArithmetic(); - } - - static bool shouldSpeculateIntegerExpectingDefined(Node& op1, Node& op2) - { - return op1.shouldSpeculateIntegerExpectingDefined() && op2.shouldSpeculateIntegerExpectingDefined(); - } - - static bool shouldSpeculateDoubleForArithmetic(Node& op1, Node& op2) - { - return op1.shouldSpeculateDoubleForArithmetic() && op2.shouldSpeculateDoubleForArithmetic(); - } - static bool shouldSpeculateNumber(Node& op1, Node& op2) { return op1.shouldSpeculateNumber() && op2.shouldSpeculateNumber(); } - static bool shouldSpeculateNumberExpectingDefined(Node& op1, Node& op2) - { - return op1.shouldSpeculateNumberExpectingDefined() && op2.shouldSpeculateNumberExpectingDefined(); - } - static bool shouldSpeculateFinalObject(Node& op1, Node& op2) { return op1.shouldSpeculateFinalObject() && op2.shouldSpeculateFinalObject(); diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp index 8356d22f9..0e45e230c 100644 --- a/Source/JavaScriptCore/dfg/DFGOperations.cpp +++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp @@ -27,9 +27,9 @@ #include "DFGOperations.h" #include "Arguments.h" -#include "ButterflyInlines.h" +#include "ButterflyInlineMethods.h" #include "CodeBlock.h" -#include "CopiedSpaceInlines.h" +#include "CopiedSpaceInlineMethods.h" #include "DFGOSRExit.h" #include "DFGRepatch.h" #include "DFGThunks.h" @@ -580,40 +580,6 @@ void DFG_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState* exec, array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot); } -void DFG_OPERATION operationPutDoubleByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, double value) -{ - JSGlobalData* globalData = &exec->globalData(); - NativeCallFrameTracer tracer(globalData, exec); - - JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value); - - if (index >= 0) { - array->putByIndexInline(exec, index, jsValue, true); - return; - } - - PutPropertySlot slot(true); - array->methodTable()->put( - array, exec, Identifier::from(exec, index), jsValue, slot); -} - -void DFG_OPERATION operationPutDoubleByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, double value) -{ - JSGlobalData* globalData = &exec->globalData(); - NativeCallFrameTracer tracer(globalData, exec); - - JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value); - - if (index >= 0) { - array->putByIndexInline(exec, index, jsValue, false); - return; - } - - PutPropertySlot slot(false); - array->methodTable()->put( - array, exec, Identifier::from(exec, index), jsValue, slot); -} - EncodedJSValue DFG_OPERATION operationArrayPush(ExecState* exec, EncodedJSValue encodedValue, JSArray* array) { JSGlobalData* globalData = &exec->globalData(); @@ -623,15 +589,6 @@ EncodedJSValue DFG_OPERATION operationArrayPush(ExecState* exec, EncodedJSValue return JSValue::encode(jsNumber(array->length())); } -EncodedJSValue DFG_OPERATION operationArrayPushDouble(ExecState* exec, double value, JSArray* array) -{ - JSGlobalData* globalData = &exec->globalData(); - NativeCallFrameTracer tracer(globalData, exec); - - array->push(exec, JSValue(JSValue::EncodeAsDouble, value)); - return JSValue::encode(jsNumber(array->length())); -} - EncodedJSValue DFG_OPERATION operationArrayPop(ExecState* exec, JSArray* array) { JSGlobalData* globalData = &exec->globalData(); @@ -1370,36 +1327,30 @@ char* DFG_OPERATION operationReallocateButterflyToGrowPropertyStorage(ExecState* return reinterpret_cast<char*>(result); } -char* DFG_OPERATION operationEnsureInt32(ExecState* exec, JSObject* object) +char* DFG_OPERATION operationEnsureContiguous(ExecState* exec, JSObject* object) { JSGlobalData& globalData = exec->globalData(); NativeCallFrameTracer tracer(&globalData, exec); - return reinterpret_cast<char*>(object->ensureInt32(globalData)); + return reinterpret_cast<char*>(object->ensureContiguous(globalData)); } -char* DFG_OPERATION operationEnsureDouble(ExecState* exec, JSObject* object) +char* DFG_OPERATION operationEnsureArrayStorage(ExecState* exec, JSObject* object) { JSGlobalData& globalData = exec->globalData(); NativeCallFrameTracer tracer(&globalData, exec); - - return reinterpret_cast<char*>(object->ensureDouble(globalData)); -} -char* DFG_OPERATION operationEnsureContiguous(ExecState* exec, JSObject* object) -{ - JSGlobalData& globalData = exec->globalData(); - NativeCallFrameTracer tracer(&globalData, exec); - - return reinterpret_cast<char*>(object->ensureContiguous(globalData)); + return reinterpret_cast<char*>(object->ensureArrayStorage(globalData)); } -char* DFG_OPERATION operationEnsureArrayStorage(ExecState* exec, JSObject* object) +char* DFG_OPERATION operationEnsureContiguousOrArrayStorage(ExecState* exec, JSObject* object, int32_t index) { JSGlobalData& globalData = exec->globalData(); NativeCallFrameTracer tracer(&globalData, exec); - return reinterpret_cast<char*>(object->ensureArrayStorage(globalData)); + if (static_cast<unsigned>(index) >= MIN_SPARSE_ARRAY_INDEX) + return reinterpret_cast<char*>(object->ensureArrayStorage(globalData)); + return reinterpret_cast<char*>(object->ensureIndexedStorage(globalData)); } double DFG_OPERATION operationFModOnInts(int32_t a, int32_t b) diff --git a/Source/JavaScriptCore/dfg/DFGOperations.h b/Source/JavaScriptCore/dfg/DFGOperations.h index b99c214e9..8d2beacec 100644 --- a/Source/JavaScriptCore/dfg/DFGOperations.h +++ b/Source/JavaScriptCore/dfg/DFGOperations.h @@ -64,7 +64,6 @@ typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EAZ)(ExecState*, JSArray*, typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ECC)(ExecState*, JSCell*, JSCell*); typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ECI)(ExecState*, JSCell*, Identifier*); typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ECJ)(ExecState*, JSCell*, EncodedJSValue); -typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EDA)(ExecState*, double, JSArray*); typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EGriJsgI)(ExecState*, ResolveOperation*, JSGlobalObject*, Identifier*); typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EI)(ExecState*, Identifier*); typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EIRo)(ExecState*, Identifier*, ResolveOperations*); @@ -93,7 +92,6 @@ typedef size_t DFG_OPERATION (*S_DFGOperation_ECC)(ExecState*, JSCell*, JSCell*) typedef size_t DFG_OPERATION (*S_DFGOperation_EJ)(ExecState*, EncodedJSValue); typedef size_t DFG_OPERATION (*S_DFGOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue); typedef size_t DFG_OPERATION (*S_DFGOperation_J)(EncodedJSValue); -typedef void DFG_OPERATION (*V_DFGOperation_EOZD)(ExecState*, JSObject*, int32_t, double); typedef void DFG_OPERATION (*V_DFGOperation_EOZJ)(ExecState*, JSObject*, int32_t, EncodedJSValue); typedef void DFG_OPERATION (*V_DFGOperation_EC)(ExecState*, JSCell*); typedef void DFG_OPERATION (*V_DFGOperation_ECIcf)(ExecState*, JSCell*, InlineCallFrame*); @@ -150,10 +148,7 @@ void DFG_OPERATION operationPutByValCellStrict(ExecState*, JSCell*, EncodedJSVal void DFG_OPERATION operationPutByValCellNonStrict(ExecState*, JSCell*, EncodedJSValue encodedProperty, EncodedJSValue encodedValue) WTF_INTERNAL; void DFG_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState*, JSObject*, int32_t index, EncodedJSValue encodedValue) WTF_INTERNAL; void DFG_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState*, JSObject*, int32_t index, EncodedJSValue encodedValue) WTF_INTERNAL; -void DFG_OPERATION operationPutDoubleByValBeyondArrayBoundsStrict(ExecState*, JSObject*, int32_t index, double value) WTF_INTERNAL; -void DFG_OPERATION operationPutDoubleByValBeyondArrayBoundsNonStrict(ExecState*, JSObject*, int32_t index, double value) WTF_INTERNAL; EncodedJSValue DFG_OPERATION operationArrayPush(ExecState*, EncodedJSValue encodedValue, JSArray*) WTF_INTERNAL; -EncodedJSValue DFG_OPERATION operationArrayPushDouble(ExecState*, double value, JSArray*) WTF_INTERNAL; EncodedJSValue DFG_OPERATION operationArrayPop(ExecState*, JSArray*) WTF_INTERNAL; EncodedJSValue DFG_OPERATION operationArrayPopAndRecoverLength(ExecState*, JSArray*) WTF_INTERNAL; EncodedJSValue DFG_OPERATION operationRegExpExec(ExecState*, JSCell*, JSCell*) WTF_INTERNAL; @@ -200,10 +195,9 @@ char* DFG_OPERATION operationAllocatePropertyStorageWithInitialCapacity(ExecStat char* DFG_OPERATION operationAllocatePropertyStorage(ExecState*, size_t newSize) WTF_INTERNAL; char* DFG_OPERATION operationReallocateButterflyToHavePropertyStorageWithInitialCapacity(ExecState*, JSObject*) WTF_INTERNAL; char* DFG_OPERATION operationReallocateButterflyToGrowPropertyStorage(ExecState*, JSObject*, size_t newSize) WTF_INTERNAL; -char* DFG_OPERATION operationEnsureInt32(ExecState*, JSObject*); -char* DFG_OPERATION operationEnsureDouble(ExecState*, JSObject*); char* DFG_OPERATION operationEnsureContiguous(ExecState*, JSObject*); char* DFG_OPERATION operationEnsureArrayStorage(ExecState*, JSObject*); +char* DFG_OPERATION operationEnsureContiguousOrArrayStorage(ExecState*, JSObject*, int32_t); // This method is used to lookup an exception hander, keyed by faultLocation, which is // the return location from one of the calls out to one of the helper operations above. diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp index b5fde4eee..3e8ead5c6 100644 --- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp @@ -225,6 +225,24 @@ private: break; } + case ArithMod: { + SpeculatedType left = m_graph[node.child1()].prediction(); + SpeculatedType right = m_graph[node.child2()].prediction(); + + if (left && right) { + if (isInt32Speculation(mergeSpeculations(left, right)) + && nodeCanSpeculateInteger(node.arithNodeFlags())) + changed |= mergePrediction(SpecInt32); + else + changed |= mergePrediction(SpecDouble); + } + + flags |= NodeUsedAsValue; + changed |= m_graph[node.child1()].mergeFlags(flags); + changed |= m_graph[node.child2()].mergeFlags(flags); + break; + } + case UInt32ToNumber: { if (nodeCanSpeculateInteger(node.arithNodeFlags())) changed |= mergePrediction(SpecInt32); @@ -240,7 +258,7 @@ private: SpeculatedType right = m_graph[node.child2()].prediction(); if (left && right) { - if (isNumberSpeculationExpectingDefined(left) && isNumberSpeculationExpectingDefined(right)) { + if (isNumberSpeculation(left) && isNumberSpeculation(right)) { if (m_graph.addShouldSpeculateInteger(node)) changed |= mergePrediction(SpecInt32); else @@ -315,7 +333,7 @@ private: SpeculatedType right = m_graph[node.child2()].prediction(); if (left && right) { - if (Node::shouldSpeculateIntegerForArithmetic(m_graph[node.child1()], m_graph[node.child2()]) + if (isInt32Speculation(mergeSpeculations(left, right)) && nodeCanSpeculateInteger(node.arithNodeFlags())) changed |= mergePrediction(SpecInt32); else @@ -355,7 +373,7 @@ private: SpeculatedType right = m_graph[node.child2()].prediction(); if (left && right) { - if (Node::shouldSpeculateIntegerForArithmetic(m_graph[node.child1()], m_graph[node.child2()]) + if (isInt32Speculation(mergeSpeculations(left, right)) && nodeCanSpeculateInteger(node.arithNodeFlags())) changed |= mergePrediction(SpecInt32); else @@ -364,7 +382,7 @@ private: // As soon as a multiply happens, we can easily end up in the part // of the double domain where the point at which you do truncation - // can change the outcome. So, ArithDiv always checks for overflow + // can change the outcome. So, ArithMul always checks for overflow // no matter what, and always forces its inputs to check as well. flags |= NodeUsedAsNumber | NodeNeedsNegZero; @@ -373,24 +391,6 @@ private: break; } - case ArithMod: { - SpeculatedType left = m_graph[node.child1()].prediction(); - SpeculatedType right = m_graph[node.child2()].prediction(); - - if (left && right) { - if (Node::shouldSpeculateIntegerForArithmetic(m_graph[node.child1()], m_graph[node.child2()]) - && nodeCanSpeculateInteger(node.arithNodeFlags())) - changed |= mergePrediction(SpecInt32); - else - changed |= mergePrediction(SpecDouble); - } - - flags |= NodeUsedAsValue; - changed |= m_graph[node.child1()].mergeFlags(flags); - changed |= m_graph[node.child2()].mergeFlags(flags); - break; - } - case ArithSqrt: { changed |= setPrediction(SpecDouble); changed |= m_graph[node.child1()].mergeFlags(flags | NodeUsedAsValue); @@ -399,11 +399,10 @@ private: case ArithAbs: { SpeculatedType child = m_graph[node.child1()].prediction(); - if (isInt32SpeculationForArithmetic(child) - && nodeCanSpeculateInteger(node.arithNodeFlags())) - changed |= mergePrediction(SpecInt32); + if (nodeCanSpeculateInteger(node.arithNodeFlags())) + changed |= mergePrediction(child); else - changed |= mergePrediction(speculatedDoubleTypeForPrediction(child)); + changed |= setPrediction(speculatedDoubleTypeForPrediction(child)); flags &= ~NodeNeedsNegZero; changed |= m_graph[node.child1()].mergeFlags(flags); @@ -777,7 +776,7 @@ private: DoubleBallot ballot; - if (isNumberSpeculationExpectingDefined(left) && isNumberSpeculationExpectingDefined(right) + if (isNumberSpeculation(left) && isNumberSpeculation(right) && !m_graph.addShouldSpeculateInteger(node)) ballot = VoteDouble; else @@ -815,7 +814,7 @@ private: DoubleBallot ballot; if (isNumberSpeculation(left) && isNumberSpeculation(right) - && !(Node::shouldSpeculateIntegerForArithmetic(m_graph[node.child1()], m_graph[node.child1()]) + && !(Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child1()]) && node.canSpeculateInteger())) ballot = VoteDouble; else @@ -828,7 +827,7 @@ private: case ArithAbs: DoubleBallot ballot; - if (!(m_graph[node.child1()].shouldSpeculateIntegerForArithmetic() + if (!(m_graph[node.child1()].shouldSpeculateInteger() && node.canSpeculateInteger())) ballot = VoteDouble; else @@ -850,24 +849,6 @@ private: break; } - case PutByVal: - case PutByValAlias: { - Edge child1 = m_graph.varArgChild(node, 0); - Edge child2 = m_graph.varArgChild(node, 1); - Edge child3 = m_graph.varArgChild(node, 2); - m_graph.vote(child1, VoteValue); - m_graph.vote(child2, VoteValue); - switch (node.arrayMode().type()) { - case Array::Double: - m_graph.vote(child3, VoteDouble); - break; - default: - m_graph.vote(child3, VoteValue); - break; - } - break; - } - default: m_graph.vote(node, VoteValue); break; diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp index 829bc14ff..6bedd6d68 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp @@ -59,7 +59,7 @@ SpeculativeJIT::~SpeculativeJIT() void SpeculativeJIT::emitAllocateJSArray(Structure* structure, GPRReg resultGPR, GPRReg storageGPR, unsigned numElements) { - ASSERT(hasUndecided(structure->indexingType()) || hasInt32(structure->indexingType()) || hasDouble(structure->indexingType()) || hasContiguous(structure->indexingType())); + ASSERT(hasContiguous(structure->indexingType())); GPRTemporary scratch(this); GPRReg scratchGPR = scratch.gpr(); @@ -67,7 +67,6 @@ void SpeculativeJIT::emitAllocateJSArray(Structure* structure, GPRReg resultGPR, unsigned vectorLength = std::max(BASE_VECTOR_LEN, numElements); JITCompiler::JumpList slowCases; - slowCases.append( emitAllocateBasicStorage(TrustedImm32(vectorLength * sizeof(JSValue) + sizeof(IndexingHeader)), storageGPR)); m_jit.subPtr(TrustedImm32(vectorLength * sizeof(JSValue)), storageGPR); @@ -80,21 +79,6 @@ void SpeculativeJIT::emitAllocateJSArray(Structure* structure, GPRReg resultGPR, m_jit.store32(TrustedImm32(numElements), MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); m_jit.store32(TrustedImm32(vectorLength), MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength())); - if (hasDouble(structure->indexingType()) && numElements < vectorLength) { -#if USE(JSVALUE64) - m_jit.move(TrustedImm64(bitwise_cast<int64_t>(QNaN)), scratchGPR); - for (unsigned i = numElements; i < vectorLength; ++i) - m_jit.store64(scratchGPR, MacroAssembler::Address(storageGPR, sizeof(double) * i)); -#else - EncodedValueDescriptor value; - value.asInt64 = JSValue::encode(JSValue(JSValue::EncodeAsDouble, QNaN)); - for (unsigned i = numElements; i < vectorLength; ++i) { - m_jit.store32(TrustedImm32(value.asBits.tag), MacroAssembler::Address(storageGPR, sizeof(double) * i + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); - m_jit.store32(TrustedImm32(value.asBits.payload), MacroAssembler::Address(storageGPR, sizeof(double) * i + OBJECT_OFFSETOF(JSValue, u.asBits.payload))); - } -#endif - } - // I want a slow path that also loads out the storage pointer, and that's // what this custom CallArrayAllocatorSlowPathGenerator gives me. It's a lot // of work for a very small piece of functionality. :-/ @@ -359,31 +343,24 @@ const TypedArrayDescriptor* SpeculativeJIT::typedArrayDescriptor(ArrayMode array } } -JITCompiler::Jump SpeculativeJIT::jumpSlowForUnwantedArrayMode(GPRReg tempGPR, ArrayMode arrayMode, IndexingType shape, bool invert) -{ - if (arrayMode.isJSArray()) { - m_jit.and32(TrustedImm32(IsArray | IndexingShapeMask), tempGPR); - return m_jit.branch32( - invert ? MacroAssembler::Equal : MacroAssembler::NotEqual, tempGPR, TrustedImm32(IsArray | shape)); - } - m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR); - return m_jit.branch32(invert ? MacroAssembler::Equal : MacroAssembler::NotEqual, tempGPR, TrustedImm32(shape)); -} - JITCompiler::JumpList SpeculativeJIT::jumpSlowForUnwantedArrayMode(GPRReg tempGPR, ArrayMode arrayMode, bool invert) { JITCompiler::JumpList result; switch (arrayMode.type()) { - case Array::Int32: - return jumpSlowForUnwantedArrayMode(tempGPR, arrayMode, Int32Shape, invert); - - case Array::Double: - return jumpSlowForUnwantedArrayMode(tempGPR, arrayMode, DoubleShape, invert); - - case Array::Contiguous: - return jumpSlowForUnwantedArrayMode(tempGPR, arrayMode, ContiguousShape, invert); - + case Array::Contiguous: { + if (arrayMode.isJSArray()) { + m_jit.and32(TrustedImm32(IsArray | IndexingShapeMask), tempGPR); + result.append( + m_jit.branch32( + invert ? MacroAssembler::Equal : MacroAssembler::NotEqual, tempGPR, TrustedImm32(IsArray | ContiguousShape))); + break; + } + m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR); + result.append( + m_jit.branch32(invert ? MacroAssembler::Equal : MacroAssembler::NotEqual, tempGPR, TrustedImm32(ContiguousShape))); + break; + } case Array::ArrayStorage: case Array::SlowPutArrayStorage: { if (arrayMode.isJSArray()) { @@ -460,8 +437,6 @@ void SpeculativeJIT::checkArray(Node& node) case Array::String: expectedClassInfo = &JSString::s_info; break; - case Array::Int32: - case Array::Double: case Array::Contiguous: case Array::ArrayStorage: case Array::SlowPutArrayStorage: { @@ -553,30 +528,16 @@ void SpeculativeJIT::arrayify(Node& node, GPRReg baseReg, GPRReg propertyReg) // If we're allegedly creating contiguous storage and the index is bogus, then // just don't. - if (propertyReg != InvalidGPRReg) { - switch (node.arrayMode().type()) { - case Array::Int32: - case Array::Double: - case Array::Contiguous: - speculationCheck( - Uncountable, JSValueRegs(), NoNode, - m_jit.branch32( - MacroAssembler::AboveOrEqual, propertyReg, TrustedImm32(MIN_SPARSE_ARRAY_INDEX))); - break; - default: - break; - } + if (node.arrayMode().type() == Array::Contiguous && propertyReg != InvalidGPRReg) { + speculationCheck( + Uncountable, JSValueRegs(), NoNode, + m_jit.branch32( + MacroAssembler::AboveOrEqual, propertyReg, TrustedImm32(MIN_SPARSE_ARRAY_INDEX))); } // Now call out to create the array storage. silentSpillAllRegisters(tempGPR); switch (node.arrayMode().type()) { - case Array::Int32: - callOperation(operationEnsureInt32, tempGPR, baseReg); - break; - case Array::Double: - callOperation(operationEnsureDouble, tempGPR, baseReg); - break; case Array::Contiguous: callOperation(operationEnsureContiguous, tempGPR, baseReg); break; @@ -1836,85 +1797,6 @@ ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSo return ValueRecovery(); } -void SpeculativeJIT::compileDoublePutByVal(Node& node, SpeculateCellOperand& base, SpeculateStrictInt32Operand& property) -{ - Edge child3 = m_jit.graph().varArgChild(node, 2); - Edge child4 = m_jit.graph().varArgChild(node, 3); - - ArrayMode arrayMode = node.arrayMode(); - - GPRReg baseReg = base.gpr(); - GPRReg propertyReg = property.gpr(); - - SpeculateDoubleOperand value(this, child3); - - FPRReg valueReg = value.fpr(); - - if (!isRealNumberSpeculation(m_state.forNode(child3).m_type)) { - // FIXME: We need a way of profiling these, and we need to hoist them into - // SpeculateDoubleOperand. - speculationCheck( - BadType, JSValueRegs(), NoNode, - m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueReg, valueReg)); - } - - if (!m_compileOkay) - return; - - StorageOperand storage(this, child4); - GPRReg storageReg = storage.gpr(); - - if (node.op() == PutByValAlias) { - // Store the value to the array. - GPRReg propertyReg = property.gpr(); - FPRReg valueReg = value.fpr(); - m_jit.storeDouble(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight)); - - noResult(m_compileIndex); - return; - } - - GPRTemporary temporary; - GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node); - - MacroAssembler::JumpList slowCases; - - if (arrayMode.isInBounds()) { - speculationCheck( - Uncountable, JSValueRegs(), NoNode, - m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); - } else { - MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())); - - slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength()))); - - if (!arrayMode.isOutOfBounds()) - speculationCheck(Uncountable, JSValueRegs(), NoNode, slowCases); - - m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg); - m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())); - - inBounds.link(&m_jit); - } - - m_jit.storeDouble(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight)); - - base.use(); - property.use(); - value.use(); - storage.use(); - - if (arrayMode.isOutOfBounds()) { - addSlowPathGenerator( - slowPathCall( - slowCases, this, - m_jit.codeBlock()->isStrictMode() ? operationPutDoubleByValBeyondArrayBoundsStrict : operationPutDoubleByValBeyondArrayBoundsNonStrict, - NoResult, baseReg, propertyReg, valueReg)); - } - - noResult(m_compileIndex, UseChildrenCalledExplicitly); -} - void SpeculativeJIT::compileGetCharCodeAt(Node& node) { SpeculateCellOperand string(this, node.child1()); @@ -2881,7 +2763,7 @@ void SpeculativeJIT::compileAdd(Node& node) return; } - if (Node::shouldSpeculateNumberExpectingDefined(at(node.child1()), at(node.child2()))) { + if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) { SpeculateDoubleOperand op1(this, node.child1()); SpeculateDoubleOperand op2(this, node.child2()); FPRTemporary result(this, op1, op2); @@ -3119,7 +3001,7 @@ void SpeculativeJIT::compileIntegerArithDivForX86(Node& node) void SpeculativeJIT::compileArithMod(Node& node) { - if (Node::shouldSpeculateIntegerForArithmetic(at(node.child1()), at(node.child2())) + if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) { compileSoftModulo(node); return; @@ -3454,8 +3336,6 @@ void SpeculativeJIT::compileGetArrayLength(Node& node) const TypedArrayDescriptor* descriptor = typedArrayDescriptor(node.arrayMode()); switch (node.arrayMode().type()) { - case Array::Int32: - case Array::Double: case Array::Contiguous: { StorageOperand storage(this, node.child2()); GPRTemporary result(this, storage); diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h index 059d3a6c6..446ea7dbe 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h @@ -1308,11 +1308,6 @@ public: m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(identifier)); return appendCallWithExceptionCheckSetResult(operation, result); } - JITCompiler::Call callOperation(J_DFGOperation_EDA operation, GPRReg result, FPRReg arg1, GPRReg arg2) - { - m_jit.setupArgumentsWithExecState(arg1, arg2); - return appendCallWithExceptionCheckSetResult(operation, result); - } JITCompiler::Call callOperation(J_DFGOperation_EJA operation, GPRReg result, GPRReg arg1, GPRReg arg2) { m_jit.setupArgumentsWithExecState(arg1, arg2); @@ -1458,11 +1453,6 @@ public: m_jit.setupArgumentsWithExecState(arg1, arg2, arg3); return appendCallWithExceptionCheck(operation); } - JITCompiler::Call callOperation(V_DFGOperation_EOZD operation, GPRReg arg1, GPRReg arg2, FPRReg arg3) - { - m_jit.setupArgumentsWithExecState(arg1, arg2, arg3); - return appendCallWithExceptionCheck(operation); - } JITCompiler::Call callOperation(V_DFGOperation_EOZJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3) { m_jit.setupArgumentsWithExecState(arg1, arg2, arg3); @@ -1671,21 +1661,11 @@ public: m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, TrustedImm32(arg1Tag), TrustedImmPtr(identifier)); return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag); } - JITCompiler::Call callOperation(J_DFGOperation_EDA operation, GPRReg resultTag, GPRReg resultPayload, FPRReg arg1, GPRReg arg2) - { - m_jit.setupArgumentsWithExecState(arg1, arg2); - return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag); - } JITCompiler::Call callOperation(J_DFGOperation_EJA operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2) { m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, arg2); return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag); } - JITCompiler::Call callOperation(J_DFGOperation_EJA operation, GPRReg resultTag, GPRReg resultPayload, TrustedImm32 arg1Tag, GPRReg arg1Payload, GPRReg arg2) - { - m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, arg2); - return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag); - } JITCompiler::Call callOperation(J_DFGOperation_EJ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload) { m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag); @@ -1839,21 +1819,11 @@ public: m_jit.setupArgumentsWithExecState(arg1, arg2, EABI_32BIT_DUMMY_ARG arg3Payload, arg3Tag); return appendCallWithExceptionCheck(operation); } - JITCompiler::Call callOperation(V_DFGOperation_EOZD operation, GPRReg arg1, GPRReg arg2, FPRReg arg3) - { - m_jit.setupArgumentsWithExecState(arg1, arg2, arg3); - return appendCallWithExceptionCheck(operation); - } JITCompiler::Call callOperation(V_DFGOperation_EOZJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3Tag, GPRReg arg3Payload) { m_jit.setupArgumentsWithExecState(arg1, arg2, EABI_32BIT_DUMMY_ARG arg3Payload, arg3Tag); return appendCallWithExceptionCheck(operation); } - JITCompiler::Call callOperation(V_DFGOperation_EOZJ operation, GPRReg arg1, GPRReg arg2, TrustedImm32 arg3Tag, GPRReg arg3Payload) - { - m_jit.setupArgumentsWithExecState(arg1, arg2, EABI_32BIT_DUMMY_ARG arg3Payload, arg3Tag); - return appendCallWithExceptionCheck(operation); - } JITCompiler::Call callOperation(V_DFGOperation_W operation, WatchpointSet* watchpointSet) { m_jit.setupArguments(TrustedImmPtr(watchpointSet)); @@ -2300,11 +2270,6 @@ public: void compileAllocatePropertyStorage(Node&); void compileReallocatePropertyStorage(Node&); -#if USE(JSVALUE32_64) - template<typename BaseOperandType, typename PropertyOperandType, typename ValueOperandType, typename TagType> - void compileContiguousPutByVal(Node&, BaseOperandType&, PropertyOperandType&, ValueOperandType&, GPRReg valuePayloadReg, TagType valueTag); -#endif - void compileDoublePutByVal(Node&, SpeculateCellOperand& base, SpeculateStrictInt32Operand& property); bool putByValWillNeedExtraRegister(ArrayMode arrayMode) { return arrayMode.mayStoreToHole(); @@ -2450,7 +2415,6 @@ public: const TypedArrayDescriptor* typedArrayDescriptor(ArrayMode); - JITCompiler::Jump jumpSlowForUnwantedArrayMode(GPRReg tempWithIndexingTypeReg, ArrayMode, IndexingType, bool invert); JITCompiler::JumpList jumpSlowForUnwantedArrayMode(GPRReg tempWithIndexingTypeReg, ArrayMode, bool invert = false); void checkArray(Node&); void arrayify(Node&, GPRReg baseReg, GPRReg propertyReg); @@ -2991,11 +2955,6 @@ public: m_gprOrInvalid = m_jit->fillSpeculateInt(index(), m_format); return m_gprOrInvalid; } - - void use() - { - m_jit->use(m_index); - } private: SpeculativeJIT* m_jit; @@ -3076,11 +3035,6 @@ public: m_fprOrInvalid = m_jit->fillSpeculateDouble(index()); return m_fprOrInvalid; } - - void use() - { - m_jit->use(m_index); - } private: SpeculativeJIT* m_jit; diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp index 694f1452e..65fdf5593 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp @@ -2046,69 +2046,6 @@ void SpeculativeJIT::emitBranch(Node& node) } } -template<typename BaseOperandType, typename PropertyOperandType, typename ValueOperandType, typename TagType> -void SpeculativeJIT::compileContiguousPutByVal(Node& node, BaseOperandType& base, PropertyOperandType& property, ValueOperandType& value, GPRReg valuePayloadReg, TagType valueTag) -{ - Edge child4 = m_jit.graph().varArgChild(node, 3); - - ArrayMode arrayMode = node.arrayMode(); - - GPRReg baseReg = base.gpr(); - GPRReg propertyReg = property.gpr(); - - StorageOperand storage(this, child4); - GPRReg storageReg = storage.gpr(); - - if (node.op() == PutByValAlias) { - // Store the value to the array. - GPRReg propertyReg = property.gpr(); - m_jit.store32(valueTag, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag))); - m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload))); - - noResult(m_compileIndex); - return; - } - - MacroAssembler::JumpList slowCases; - - if (arrayMode.isInBounds()) { - speculationCheck( - Uncountable, JSValueRegs(), NoNode, - m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); - } else { - MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())); - - slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength()))); - - if (!arrayMode.isOutOfBounds()) - speculationCheck(Uncountable, JSValueRegs(), NoNode, slowCases); - - m_jit.add32(TrustedImm32(1), propertyReg); - m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())); - m_jit.sub32(TrustedImm32(1), propertyReg); - - inBounds.link(&m_jit); - } - - m_jit.store32(valueTag, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag))); - m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload))); - - base.use(); - property.use(); - value.use(); - storage.use(); - - if (arrayMode.isOutOfBounds()) { - addSlowPathGenerator( - slowPathCall( - slowCases, this, - m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict, - NoResult, baseReg, propertyReg, valueTag, valuePayloadReg)); - } - - noResult(m_compileIndex, UseChildrenCalledExplicitly); -} - void SpeculativeJIT::compile(Node& node) { NodeType op = node.op(); @@ -2429,8 +2366,7 @@ void SpeculativeJIT::compile(Node& node) break; case ArithDiv: { - if (Node::shouldSpeculateIntegerForArithmetic(at(node.child1()), at(node.child2())) - && node.canSpeculateInteger()) { + if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) { #if CPU(X86) compileIntegerArithDivForX86(node); #else // CPU(X86) -> so non-X86 code follows @@ -2457,8 +2393,7 @@ void SpeculativeJIT::compile(Node& node) } case ArithAbs: { - if (at(node.child1()).shouldSpeculateIntegerForArithmetic() - && node.canSpeculateInteger()) { + if (at(node.child1()).shouldSpeculateInteger() && node.canSpeculateInteger()) { SpeculateIntegerOperand op1(this, node.child1()); GPRTemporary result(this, op1); GPRTemporary scratch(this); @@ -2482,8 +2417,7 @@ void SpeculativeJIT::compile(Node& node) case ArithMin: case ArithMax: { - if (Node::shouldSpeculateIntegerForArithmetic(at(node.child1()), at(node.child2())) - && node.canSpeculateInteger()) { + if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) { SpeculateStrictInt32Operand op1(this, node.child1()); SpeculateStrictInt32Operand op2(this, node.child2()); GPRTemporary result(this, op1); @@ -2633,7 +2567,6 @@ void SpeculativeJIT::compile(Node& node) jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex); break; } - case Array::Int32: case Array::Contiguous: { if (node.arrayMode().isInBounds()) { SpeculateStrictInt32Operand property(this, node.child2()); @@ -2647,20 +2580,8 @@ void SpeculativeJIT::compile(Node& node) speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); - GPRTemporary resultPayload(this); - if (node.arrayMode().type() == Array::Int32) { - speculationCheck( - OutOfBounds, JSValueRegs(), NoNode, - m_jit.branch32( - MacroAssembler::Equal, - MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), - TrustedImm32(JSValue::EmptyValueTag))); - m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr()); - integerResult(resultPayload.gpr(), m_compileIndex); - break; - } - GPRTemporary resultTag(this); + GPRTemporary resultPayload(this); m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag.gpr()); speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::Equal, resultTag.gpr(), TrustedImm32(JSValue::EmptyValueTag))); m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr()); @@ -2700,60 +2621,6 @@ void SpeculativeJIT::compile(Node& node) jsValueResult(resultTagReg, resultPayloadReg, m_compileIndex); break; } - case Array::Double: { - if (node.arrayMode().isInBounds()) { - SpeculateStrictInt32Operand property(this, node.child2()); - StorageOperand storage(this, node.child3()); - - GPRReg propertyReg = property.gpr(); - GPRReg storageReg = storage.gpr(); - - if (!m_compileOkay) - return; - - speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); - - FPRTemporary result(this); - m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr()); - speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, result.fpr(), result.fpr())); - doubleResult(result.fpr(), m_compileIndex); - break; - } - - SpeculateCellOperand base(this, node.child1()); - SpeculateStrictInt32Operand property(this, node.child2()); - StorageOperand storage(this, node.child3()); - - GPRReg baseReg = base.gpr(); - GPRReg propertyReg = property.gpr(); - GPRReg storageReg = storage.gpr(); - - if (!m_compileOkay) - return; - - GPRTemporary resultTag(this); - GPRTemporary resultPayload(this); - FPRTemporary temp(this); - GPRReg resultTagReg = resultTag.gpr(); - GPRReg resultPayloadReg = resultPayload.gpr(); - FPRReg tempReg = temp.fpr(); - - MacroAssembler::JumpList slowCases; - - slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); - - m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg); - slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempReg, tempReg)); - boxDouble(tempReg, resultTagReg, resultPayloadReg); - - addSlowPathGenerator( - slowPathCall( - slowCases, this, operationGetByValArrayInt, - JSValueRegs(resultTagReg, resultPayloadReg), baseReg, propertyReg)); - - jsValueResult(resultTagReg, resultPayloadReg, m_compileIndex); - break; - } case Array::ArrayStorage: case Array::SlowPutArrayStorage: { if (node.arrayMode().isInBounds()) { @@ -2904,17 +2771,6 @@ void SpeculativeJIT::compile(Node& node) GPRReg propertyReg = property.gpr(); switch (arrayMode.type()) { - case Array::Int32: { - SpeculateIntegerOperand value(this, child3); - - GPRReg valuePayloadReg = value.gpr(); - - if (!m_compileOkay) - return; - - compileContiguousPutByVal(node, base, property, value, valuePayloadReg, TrustedImm32(JSValue::Int32Tag)); - break; - } case Array::Contiguous: { JSValueOperand value(this, child3); @@ -2928,14 +2784,61 @@ void SpeculativeJIT::compile(Node& node) GPRTemporary scratch(this); writeBarrier(baseReg, valueTagReg, child3, WriteBarrierForPropertyAccess, scratch.gpr()); } + + StorageOperand storage(this, child4); + GPRReg storageReg = storage.gpr(); + + if (node.op() == PutByValAlias) { + // Store the value to the array. + GPRReg propertyReg = property.gpr(); + m_jit.store32(valueTagReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag))); + m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload))); + + noResult(m_compileIndex); + break; + } - compileContiguousPutByVal(node, base, property, value, valuePayloadReg, valueTagReg); - break; - } - case Array::Double: { - compileDoublePutByVal(node, base, property); + MacroAssembler::JumpList slowCases; + + if (arrayMode.isInBounds()) { + speculationCheck( + Uncountable, JSValueRegs(), NoNode, + m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); + } else { + MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())); + + slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength()))); + + if (!arrayMode.isOutOfBounds()) + speculationCheck(Uncountable, JSValueRegs(), NoNode, slowCases); + + m_jit.add32(TrustedImm32(1), propertyReg); + m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())); + m_jit.sub32(TrustedImm32(1), propertyReg); + + inBounds.link(&m_jit); + } + + m_jit.store32(valueTagReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag))); + m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload))); + + base.use(); + property.use(); + value.use(); + storage.use(); + + if (arrayMode.isOutOfBounds()) { + addSlowPathGenerator( + slowPathCall( + slowCases, this, + m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict, + NoResult, baseReg, propertyReg, valueTagReg, valuePayloadReg)); + } + + noResult(m_compileIndex, UseChildrenCalledExplicitly); break; } + case Array::ArrayStorage: case Array::SlowPutArrayStorage: { JSValueOperand value(this, child3); @@ -3125,47 +3028,24 @@ void SpeculativeJIT::compile(Node& node) ASSERT(node.arrayMode().isJSArray()); SpeculateCellOperand base(this, node.child1()); + JSValueOperand value(this, node.child2()); GPRTemporary storageLength(this); GPRReg baseGPR = base.gpr(); + GPRReg valueTagGPR = value.tagGPR(); + GPRReg valuePayloadGPR = value.payloadGPR(); GPRReg storageLengthGPR = storageLength.gpr(); + if (Heap::isWriteBarrierEnabled()) { + GPRTemporary scratch(this); + writeBarrier(baseGPR, valueTagGPR, node.child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR); + } + StorageOperand storage(this, node.child3()); GPRReg storageGPR = storage.gpr(); switch (node.arrayMode().type()) { - case Array::Int32: { - SpeculateIntegerOperand value(this, node.child2()); - GPRReg valuePayloadGPR = value.gpr(); - - m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR); - MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength())); - m_jit.store32(TrustedImm32(JSValue::Int32Tag), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag))); - m_jit.store32(valuePayloadGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload))); - m_jit.add32(TrustedImm32(1), storageLengthGPR); - m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); - m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR); - - addSlowPathGenerator( - slowPathCall( - slowPath, this, operationArrayPush, - JSValueRegs(storageGPR, storageLengthGPR), - TrustedImm32(JSValue::Int32Tag), valuePayloadGPR, baseGPR)); - - jsValueResult(storageGPR, storageLengthGPR, m_compileIndex); - break; - } - case Array::Contiguous: { - JSValueOperand value(this, node.child2()); - GPRReg valueTagGPR = value.tagGPR(); - GPRReg valuePayloadGPR = value.payloadGPR(); - - if (Heap::isWriteBarrierEnabled()) { - GPRTemporary scratch(this); - writeBarrier(baseGPR, valueTagGPR, node.child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR); - } - m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR); MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength())); m_jit.store32(valueTagGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag))); @@ -3184,45 +3064,7 @@ void SpeculativeJIT::compile(Node& node) break; } - case Array::Double: { - SpeculateDoubleOperand value(this, node.child2()); - FPRReg valueFPR = value.fpr(); - - if (!isRealNumberSpeculation(m_state.forNode(node.child2()).m_type)) { - // FIXME: We need a way of profiling these, and we need to hoist them into - // SpeculateDoubleOperand. - speculationCheck( - BadType, JSValueRegs(), NoNode, - m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueFPR, valueFPR)); - } - - m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR); - MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength())); - m_jit.storeDouble(valueFPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight)); - m_jit.add32(TrustedImm32(1), storageLengthGPR); - m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); - m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR); - - addSlowPathGenerator( - slowPathCall( - slowPath, this, operationArrayPushDouble, - JSValueRegs(storageGPR, storageLengthGPR), - valueFPR, baseGPR)); - - jsValueResult(storageGPR, storageLengthGPR, m_compileIndex); - break; - } - case Array::ArrayStorage: { - JSValueOperand value(this, node.child2()); - GPRReg valueTagGPR = value.tagGPR(); - GPRReg valuePayloadGPR = value.payloadGPR(); - - if (Heap::isWriteBarrierEnabled()) { - GPRTemporary scratch(this); - writeBarrier(baseGPR, valueTagGPR, node.child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR); - } - m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR); // Refuse to handle bizarre lengths. @@ -3265,7 +3107,6 @@ void SpeculativeJIT::compile(Node& node) GPRReg storageGPR = storage.gpr(); switch (node.arrayMode().type()) { - case Array::Int32: case Array::Contiguous: { m_jit.load32( MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), valuePayloadGPR); @@ -3299,44 +3140,6 @@ void SpeculativeJIT::compile(Node& node) break; } - case Array::Double: { - FPRTemporary temp(this); - FPRReg tempFPR = temp.fpr(); - - m_jit.load32( - MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), valuePayloadGPR); - MacroAssembler::Jump undefinedCase = - m_jit.branchTest32(MacroAssembler::Zero, valuePayloadGPR); - m_jit.sub32(TrustedImm32(1), valuePayloadGPR); - m_jit.store32( - valuePayloadGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); - m_jit.loadDouble( - MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight), - tempFPR); - MacroAssembler::Jump slowCase = m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempFPR, tempFPR); - JSValue nan = JSValue(JSValue::EncodeAsDouble, QNaN); - m_jit.store32( - MacroAssembler::TrustedImm32(nan.u.asBits.tag), - MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag))); - m_jit.store32( - MacroAssembler::TrustedImm32(nan.u.asBits.payload), - MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload))); - boxDouble(tempFPR, valueTagGPR, valuePayloadGPR); - - addSlowPathGenerator( - slowPathMove( - undefinedCase, this, - MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR, - MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR)); - addSlowPathGenerator( - slowPathCall( - slowCase, this, operationArrayPopAndRecoverLength, - JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR)); - - jsValueResult(valueTagGPR, valuePayloadGPR, m_compileIndex); - break; - } - case Array::ArrayStorage: { GPRTemporary storageLength(this); GPRReg storageLengthGPR = storageLength.gpr(); @@ -3555,17 +3358,11 @@ void SpeculativeJIT::compile(Node& node) case NewArray: { JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node.codeOrigin); - if (!globalObject->isHavingABadTime() && !hasArrayStorage(node.indexingType())) { + if (!globalObject->isHavingABadTime()) { globalObject->havingABadTimeWatchpoint()->add(speculationWatchpoint()); - Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()); - ASSERT(structure->indexingType() == node.indexingType()); - ASSERT( - hasUndecided(structure->indexingType()) - || hasInt32(structure->indexingType()) - || hasDouble(structure->indexingType()) - || hasContiguous(structure->indexingType())); - + ASSERT(hasContiguous(globalObject->arrayStructure()->indexingType())); + unsigned numElements = node.numChildren(); GPRTemporary result(this); @@ -3574,52 +3371,17 @@ void SpeculativeJIT::compile(Node& node) GPRReg resultGPR = result.gpr(); GPRReg storageGPR = storage.gpr(); - emitAllocateJSArray(structure, resultGPR, storageGPR, numElements); + emitAllocateJSArray(globalObject->arrayStructure(), resultGPR, storageGPR, numElements); // At this point, one way or another, resultGPR and storageGPR have pointers to // the JSArray and the Butterfly, respectively. - ASSERT(!hasUndecided(structure->indexingType()) || !node.numChildren()); - for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) { - Edge use = m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]; - switch (node.indexingType()) { - case ALL_BLANK_INDEXING_TYPES: - case ALL_UNDECIDED_INDEXING_TYPES: - CRASH(); - break; - case ALL_DOUBLE_INDEXING_TYPES: { - SpeculateDoubleOperand operand(this, use); - FPRReg opFPR = operand.fpr(); - if (!isRealNumberSpeculation(m_state.forNode(use).m_type)) { - // FIXME: We need a way of profiling these, and we need to hoist them into - // SpeculateDoubleOperand. - speculationCheck( - BadType, JSValueRegs(), NoNode, - m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR)); - } - - m_jit.storeDouble(opFPR, MacroAssembler::Address(storageGPR, sizeof(double) * operandIdx)); - break; - } - case ALL_INT32_INDEXING_TYPES: { - SpeculateIntegerOperand operand(this, use); - m_jit.store32(TrustedImm32(JSValue::Int32Tag), MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); - m_jit.store32(operand.gpr(), MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx + OBJECT_OFFSETOF(JSValue, u.asBits.payload))); - break; - } - case ALL_CONTIGUOUS_INDEXING_TYPES: { - JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]); - GPRReg opTagGPR = operand.tagGPR(); - GPRReg opPayloadGPR = operand.payloadGPR(); - m_jit.store32(opTagGPR, MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); - m_jit.store32(opPayloadGPR, MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx + OBJECT_OFFSETOF(JSValue, u.asBits.payload))); - break; - } - default: - CRASH(); - break; - } + JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]); + GPRReg opTagGPR = operand.tagGPR(); + GPRReg opPayloadGPR = operand.payloadGPR(); + m_jit.store32(opTagGPR, MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); + m_jit.store32(opPayloadGPR, MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx + OBJECT_OFFSETOF(JSValue, u.asBits.payload))); } // Yuck, we should *really* have a way of also returning the storageGPR. But @@ -3637,7 +3399,7 @@ void SpeculativeJIT::compile(Node& node) flushRegisters(); GPRResult result(this); callOperation( - operationNewEmptyArray, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType())); + operationNewEmptyArray, result.gpr(), globalObject->arrayStructure()); cellResult(result.gpr(), m_compileIndex); break; } @@ -3647,61 +3409,13 @@ void SpeculativeJIT::compile(Node& node) EncodedJSValue* buffer = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0; for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) { - // Need to perform the speculations that this node promises to perform. If we're - // emitting code here and the indexing type is not array storage then there is - // probably something hilarious going on and we're already failing at all the - // things, but at least we're going to be sound. - Edge use = m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]; - switch (node.indexingType()) { - case ALL_BLANK_INDEXING_TYPES: - case ALL_UNDECIDED_INDEXING_TYPES: - CRASH(); - break; - case ALL_DOUBLE_INDEXING_TYPES: { - SpeculateDoubleOperand operand(this, use); - FPRReg opFPR = operand.fpr(); - if (!isRealNumberSpeculation(m_state.forNode(use).m_type)) { - // FIXME: We need a way of profiling these, and we need to hoist them into - // SpeculateDoubleOperand. - speculationCheck( - BadType, JSValueRegs(), NoNode, - m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR)); - } - - m_jit.storeDouble(opFPR, reinterpret_cast<char*>(buffer + operandIdx)); - break; - } - case ALL_INT32_INDEXING_TYPES: { - SpeculateIntegerOperand operand(this, use); - GPRReg opGPR = operand.gpr(); - m_jit.store32(TrustedImm32(JSValue::Int32Tag), reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)); - m_jit.store32(opGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)); - break; - } - case ALL_CONTIGUOUS_INDEXING_TYPES: - case ALL_ARRAY_STORAGE_INDEXING_TYPES: { - JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]); - GPRReg opTagGPR = operand.tagGPR(); - GPRReg opPayloadGPR = operand.payloadGPR(); - - m_jit.store32(opTagGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)); - m_jit.store32(opPayloadGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)); - operand.use(); - break; - } - default: - CRASH(); - break; - } - } - - switch (node.indexingType()) { - case ALL_DOUBLE_INDEXING_TYPES: - case ALL_INT32_INDEXING_TYPES: - useChildren(node); - break; - default: - break; + JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]); + GPRReg opTagGPR = operand.tagGPR(); + GPRReg opPayloadGPR = operand.payloadGPR(); + operand.use(); + + m_jit.store32(opTagGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)); + m_jit.store32(opPayloadGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)); } flushRegisters(); @@ -3717,8 +3431,8 @@ void SpeculativeJIT::compile(Node& node) GPRResult result(this); callOperation( - operationNewArray, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()), - static_cast<void*>(buffer), node.numChildren()); + operationNewArray, result.gpr(), globalObject->arrayStructure(), + static_cast<void *>(buffer), node.numChildren()); if (scratchSize) { GPRTemporary scratch(this); @@ -3757,30 +3471,17 @@ void SpeculativeJIT::compile(Node& node) emitAllocateBasicStorage(resultGPR, storageGPR)); m_jit.subPtr(scratchGPR, storageGPR); emitAllocateBasicJSObject<JSArray, MarkedBlock::None>( - TrustedImmPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType())), resultGPR, scratchGPR, + TrustedImmPtr(globalObject->arrayStructure()), resultGPR, scratchGPR, storageGPR, sizeof(JSArray), slowCases); m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength())); - if (hasDouble(node.indexingType())) { - JSValue nan = JSValue(JSValue::EncodeAsDouble, QNaN); - - m_jit.move(sizeGPR, scratchGPR); - MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, scratchGPR); - MacroAssembler::Label loop = m_jit.label(); - m_jit.sub32(TrustedImm32(1), scratchGPR); - m_jit.store32(TrustedImm32(nan.u.asBits.tag), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag))); - m_jit.store32(TrustedImm32(nan.u.asBits.payload), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload))); - m_jit.branchTest32(MacroAssembler::NonZero, scratchGPR).linkTo(loop, &m_jit); - done.link(&m_jit); - } - addSlowPathGenerator(adoptPtr( new CallArrayAllocatorWithVariableSizeSlowPathGenerator( slowCases, this, operationNewArrayWithSize, resultGPR, - globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()), - globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage), + globalObject->arrayStructure(), + globalObject->arrayStructureWithArrayStorage(), sizeGPR))); cellResult(resultGPR, m_compileIndex); @@ -3791,24 +3492,15 @@ void SpeculativeJIT::compile(Node& node) GPRReg sizeGPR = size.gpr(); flushRegisters(); GPRResult result(this); - GPRReg resultGPR = result.gpr(); - GPRReg structureGPR = selectScratchGPR(sizeGPR); - MacroAssembler::Jump bigLength = m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_SPARSE_ARRAY_INDEX)); - m_jit.move(TrustedImmPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType())), structureGPR); - MacroAssembler::Jump done = m_jit.jump(); - bigLength.link(&m_jit); - m_jit.move(TrustedImmPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)), structureGPR); - done.link(&m_jit); callOperation( - operationNewArrayWithSize, resultGPR, structureGPR, sizeGPR); - cellResult(resultGPR, m_compileIndex); + operationNewArrayWithSize, result.gpr(), globalObject->arrayStructure(), sizeGPR); + cellResult(result.gpr(), m_compileIndex); break; } case NewArrayBuffer: { JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node.codeOrigin); - IndexingType indexingType = node.indexingType(); - if (!globalObject->isHavingABadTime() && !hasArrayStorage(indexingType)) { + if (!globalObject->isHavingABadTime()) { globalObject->havingABadTimeWatchpoint()->add(speculationWatchpoint()); unsigned numElements = node.numConstants(); @@ -3819,25 +3511,12 @@ void SpeculativeJIT::compile(Node& node) GPRReg resultGPR = result.gpr(); GPRReg storageGPR = storage.gpr(); - emitAllocateJSArray(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType), resultGPR, storageGPR, numElements); + emitAllocateJSArray(globalObject->arrayStructure(), resultGPR, storageGPR, numElements); - if (node.indexingType() == ArrayWithDouble) { - JSValue* data = m_jit.codeBlock()->constantBuffer(node.startConstant()); - for (unsigned index = 0; index < node.numConstants(); ++index) { - union { - int32_t halves[2]; - double value; - } u; - u.value = data[index].asNumber(); - m_jit.store32(Imm32(u.halves[0]), MacroAssembler::Address(storageGPR, sizeof(double) * index)); - m_jit.store32(Imm32(u.halves[1]), MacroAssembler::Address(storageGPR, sizeof(double) * index + sizeof(int32_t))); - } - } else { - int32_t* data = bitwise_cast<int32_t*>(m_jit.codeBlock()->constantBuffer(node.startConstant())); - for (unsigned index = 0; index < node.numConstants() * 2; ++index) { - m_jit.store32( - Imm32(data[index]), MacroAssembler::Address(storageGPR, sizeof(int32_t) * index)); - } + int32_t* data = bitwise_cast<int32_t*>(m_jit.codeBlock()->constantBuffer(node.startConstant())); + for (unsigned index = 0; index < node.numConstants() * 2; ++index) { + m_jit.store32( + Imm32(data[index]), MacroAssembler::Address(storageGPR, sizeof(int32_t) * index)); } cellResult(resultGPR, m_compileIndex); @@ -3847,7 +3526,7 @@ void SpeculativeJIT::compile(Node& node) flushRegisters(); GPRResult result(this); - callOperation(operationNewArrayBuffer, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()), node.startConstant(), node.numConstants()); + callOperation(operationNewArrayBuffer, result.gpr(), globalObject->arrayStructure(), node.startConstant(), node.numConstants()); cellResult(result.gpr(), m_compileIndex); break; diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp index ecd823e7b..6c066c388 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp @@ -2403,8 +2403,7 @@ void SpeculativeJIT::compile(Node& node) break; case ArithDiv: { - if (Node::shouldSpeculateIntegerForArithmetic(at(node.child1()), at(node.child2())) - && node.canSpeculateInteger()) { + if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) { compileIntegerArithDivForX86(node); break; } @@ -2427,8 +2426,7 @@ void SpeculativeJIT::compile(Node& node) } case ArithAbs: { - if (at(node.child1()).shouldSpeculateIntegerForArithmetic() - && node.canSpeculateInteger()) { + if (at(node.child1()).shouldSpeculateInteger() && node.canSpeculateInteger()) { SpeculateIntegerOperand op1(this, node.child1()); GPRTemporary result(this); GPRTemporary scratch(this); @@ -2452,8 +2450,7 @@ void SpeculativeJIT::compile(Node& node) case ArithMin: case ArithMax: { - if (Node::shouldSpeculateIntegerForArithmetic(at(node.child1()), at(node.child2())) - && node.canSpeculateInteger()) { + if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) { SpeculateStrictInt32Operand op1(this, node.child1()); SpeculateStrictInt32Operand op2(this, node.child2()); GPRTemporary result(this, op1); @@ -2601,7 +2598,6 @@ void SpeculativeJIT::compile(Node& node) jsValueResult(result.gpr(), m_compileIndex); break; } - case Array::Int32: case Array::Contiguous: { if (node.arrayMode().isInBounds()) { SpeculateStrictInt32Operand property(this, node.child2()); @@ -2618,7 +2614,7 @@ void SpeculativeJIT::compile(Node& node) GPRTemporary result(this); m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.gpr()); speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branchTest64(MacroAssembler::Zero, result.gpr())); - jsValueResult(result.gpr(), m_compileIndex, node.arrayMode().type() == Array::Int32 ? DataFormatJSInteger : DataFormatJS); + jsValueResult(result.gpr(), m_compileIndex); break; } @@ -2651,60 +2647,6 @@ void SpeculativeJIT::compile(Node& node) jsValueResult(resultReg, m_compileIndex); break; } - - case Array::Double: { - if (node.arrayMode().isInBounds()) { - SpeculateStrictInt32Operand property(this, node.child2()); - StorageOperand storage(this, node.child3()); - - GPRReg propertyReg = property.gpr(); - GPRReg storageReg = storage.gpr(); - - if (!m_compileOkay) - return; - - speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); - - FPRTemporary result(this); - m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr()); - speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, result.fpr(), result.fpr())); - doubleResult(result.fpr(), m_compileIndex); - break; - } - - SpeculateCellOperand base(this, node.child1()); - SpeculateStrictInt32Operand property(this, node.child2()); - StorageOperand storage(this, node.child3()); - - GPRReg baseReg = base.gpr(); - GPRReg propertyReg = property.gpr(); - GPRReg storageReg = storage.gpr(); - - if (!m_compileOkay) - return; - - GPRTemporary result(this); - FPRTemporary temp(this); - GPRReg resultReg = result.gpr(); - FPRReg tempReg = temp.fpr(); - - MacroAssembler::JumpList slowCases; - - slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); - - m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg); - slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempReg, tempReg)); - boxDouble(tempReg, resultReg); - - addSlowPathGenerator( - slowPathCall( - slowCases, this, operationGetByValArrayInt, - result.gpr(), baseReg, propertyReg)); - - jsValueResult(resultReg, m_compileIndex); - break; - } - case Array::ArrayStorage: case Array::SlowPutArrayStorage: { if (node.arrayMode().isInBounds()) { @@ -2847,7 +2789,6 @@ void SpeculativeJIT::compile(Node& node) GPRReg propertyReg = property.gpr(); switch (arrayMode.type()) { - case Array::Int32: case Array::Contiguous: { JSValueOperand value(this, child3); @@ -2855,15 +2796,8 @@ void SpeculativeJIT::compile(Node& node) if (!m_compileOkay) return; - - if (arrayMode.type() == Array::Int32 - && !isInt32Speculation(m_state.forNode(child3).m_type)) { - speculationCheck( - BadType, JSValueRegs(valueReg), child3, - m_jit.branch64(MacroAssembler::Below, valueReg, GPRInfo::tagTypeNumberRegister)); - } - if (arrayMode.type() == Array::Contiguous && Heap::isWriteBarrierEnabled()) { + if (Heap::isWriteBarrierEnabled()) { GPRTemporary scratch(this); writeBarrier(baseReg, value.gpr(), child3, WriteBarrierForPropertyAccess, scratch.gpr()); } @@ -2923,11 +2857,6 @@ void SpeculativeJIT::compile(Node& node) break; } - case Array::Double: { - compileDoublePutByVal(node, base, property); - break; - } - case Array::ArrayStorage: case Array::SlowPutArrayStorage: { JSValueOperand value(this, child3); @@ -3152,31 +3081,23 @@ void SpeculativeJIT::compile(Node& node) ASSERT(node.arrayMode().isJSArray()); SpeculateCellOperand base(this, node.child1()); + JSValueOperand value(this, node.child2()); GPRTemporary storageLength(this); GPRReg baseGPR = base.gpr(); + GPRReg valueGPR = value.gpr(); GPRReg storageLengthGPR = storageLength.gpr(); + if (Heap::isWriteBarrierEnabled()) { + GPRTemporary scratch(this); + writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR); + } + StorageOperand storage(this, node.child3()); GPRReg storageGPR = storage.gpr(); switch (node.arrayMode().type()) { - case Array::Int32: case Array::Contiguous: { - JSValueOperand value(this, node.child2()); - GPRReg valueGPR = value.gpr(); - - if (node.arrayMode().type() == Array::Int32 && !isInt32Speculation(m_state.forNode(node.child2()).m_type)) { - speculationCheck( - BadType, JSValueRegs(valueGPR), node.child2(), - m_jit.branch64(MacroAssembler::Below, valueGPR, GPRInfo::tagTypeNumberRegister)); - } - - if (node.arrayMode().type() != Array::Int32 && Heap::isWriteBarrierEnabled()) { - GPRTemporary scratch(this); - writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR); - } - m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR); MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength())); m_jit.store64(valueGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight)); @@ -3193,43 +3114,7 @@ void SpeculativeJIT::compile(Node& node) break; } - case Array::Double: { - SpeculateDoubleOperand value(this, node.child2()); - FPRReg valueFPR = value.fpr(); - - if (!isRealNumberSpeculation(m_state.forNode(node.child2()).m_type)) { - // FIXME: We need a way of profiling these, and we need to hoist them into - // SpeculateDoubleOperand. - speculationCheck( - BadType, JSValueRegs(), NoNode, - m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueFPR, valueFPR)); - } - - m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR); - MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength())); - m_jit.storeDouble(valueFPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight)); - m_jit.add32(TrustedImm32(1), storageLengthGPR); - m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); - m_jit.or64(GPRInfo::tagTypeNumberRegister, storageLengthGPR); - - addSlowPathGenerator( - slowPathCall( - slowPath, this, operationArrayPushDouble, NoResult, storageLengthGPR, - valueFPR, baseGPR)); - - jsValueResult(storageLengthGPR, m_compileIndex); - break; - } - case Array::ArrayStorage: { - JSValueOperand value(this, node.child2()); - GPRReg valueGPR = value.gpr(); - - if (Heap::isWriteBarrierEnabled()) { - GPRTemporary scratch(this); - writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR); - } - m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR); // Refuse to handle bizarre lengths. @@ -3267,17 +3152,13 @@ void SpeculativeJIT::compile(Node& node) StorageOperand storage(this, node.child2()); GPRTemporary value(this); GPRTemporary storageLength(this); - FPRTemporary temp(this); // This is kind of lame, since we don't always need it. I'm relying on the fact that we don't have FPR pressure, especially in code that uses pop(). GPRReg baseGPR = base.gpr(); GPRReg storageGPR = storage.gpr(); GPRReg valueGPR = value.gpr(); GPRReg storageLengthGPR = storageLength.gpr(); - FPRReg tempFPR = temp.fpr(); switch (node.arrayMode().type()) { - case Array::Int32: - case Array::Double: case Array::Contiguous: { m_jit.load32( MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR); @@ -3286,27 +3167,14 @@ void SpeculativeJIT::compile(Node& node) m_jit.sub32(TrustedImm32(1), storageLengthGPR); m_jit.store32( storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); - MacroAssembler::Jump slowCase; - if (node.arrayMode().type() == Array::Double) { - m_jit.loadDouble( - MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight), - tempFPR); - // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old - // length and the new length. - m_jit.store64( - MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight)); - slowCase = m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempFPR, tempFPR); - boxDouble(tempFPR, valueGPR); - } else { - m_jit.load64( - MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight), - valueGPR); - // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old - // length and the new length. - m_jit.store64( + m_jit.load64( + MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight), + valueGPR); + // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old + // length and the new length. + m_jit.store64( MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight)); - slowCase = m_jit.branchTest64(MacroAssembler::Zero, valueGPR); - } + MacroAssembler::Jump slowCase = m_jit.branchTest64(MacroAssembler::Zero, valueGPR); addSlowPathGenerator( slowPathMove( @@ -3316,7 +3184,6 @@ void SpeculativeJIT::compile(Node& node) slowPathCall( slowCase, this, operationArrayPopAndRecoverLength, valueGPR, baseGPR)); - // We can't know for sure that the result is an int because of the slow paths. :-/ jsValueResult(valueGPR, m_compileIndex); break; } @@ -3471,16 +3338,10 @@ void SpeculativeJIT::compile(Node& node) case NewArray: { JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node.codeOrigin); - if (!globalObject->isHavingABadTime() && !hasArrayStorage(node.indexingType())) { + if (!globalObject->isHavingABadTime()) { globalObject->havingABadTimeWatchpoint()->add(speculationWatchpoint()); - Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()); - ASSERT(structure->indexingType() == node.indexingType()); - ASSERT( - hasUndecided(structure->indexingType()) - || hasInt32(structure->indexingType()) - || hasDouble(structure->indexingType()) - || hasContiguous(structure->indexingType())); + ASSERT(hasContiguous(globalObject->arrayStructure()->indexingType())); unsigned numElements = node.numChildren(); @@ -3490,50 +3351,15 @@ void SpeculativeJIT::compile(Node& node) GPRReg resultGPR = result.gpr(); GPRReg storageGPR = storage.gpr(); - emitAllocateJSArray(structure, resultGPR, storageGPR, numElements); + emitAllocateJSArray(globalObject->arrayStructure(), resultGPR, storageGPR, numElements); // At this point, one way or another, resultGPR and storageGPR have pointers to // the JSArray and the Butterfly, respectively. - ASSERT(!hasUndecided(structure->indexingType()) || !node.numChildren()); - for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) { - Edge use = m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]; - switch (node.indexingType()) { - case ALL_BLANK_INDEXING_TYPES: - case ALL_UNDECIDED_INDEXING_TYPES: - CRASH(); - break; - case ALL_DOUBLE_INDEXING_TYPES: { - SpeculateDoubleOperand operand(this, use); - FPRReg opFPR = operand.fpr(); - if (!isRealNumberSpeculation(m_state.forNode(use).m_type)) { - // FIXME: We need a way of profiling these, and we need to hoist them into - // SpeculateDoubleOperand. - speculationCheck( - BadType, JSValueRegs(), NoNode, - m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR)); - } - - m_jit.storeDouble(opFPR, MacroAssembler::Address(storageGPR, sizeof(double) * operandIdx)); - break; - } - case ALL_INT32_INDEXING_TYPES: - case ALL_CONTIGUOUS_INDEXING_TYPES: { - JSValueOperand operand(this, use); - GPRReg opGPR = operand.gpr(); - if (hasInt32(node.indexingType()) && !isInt32Speculation(m_state.forNode(use).m_type)) { - speculationCheck( - BadType, JSValueRegs(opGPR), use.index(), - m_jit.branch64(MacroAssembler::Below, opGPR, GPRInfo::tagTypeNumberRegister)); - } - m_jit.store64(opGPR, MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx)); - break; - } - default: - CRASH(); - break; - } + JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]); + GPRReg opGPR = operand.gpr(); + m_jit.store64(opGPR, MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx)); } // Yuck, we should *really* have a way of also returning the storageGPR. But @@ -3550,7 +3376,7 @@ void SpeculativeJIT::compile(Node& node) if (!node.numChildren()) { flushRegisters(); GPRResult result(this); - callOperation(operationNewEmptyArray, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType())); + callOperation(operationNewEmptyArray, result.gpr(), globalObject->arrayStructure()); cellResult(result.gpr(), m_compileIndex); break; } @@ -3560,65 +3386,11 @@ void SpeculativeJIT::compile(Node& node) EncodedJSValue* buffer = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0; for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) { - // Need to perform the speculations that this node promises to perform. If we're - // emitting code here and the indexing type is not array storage then there is - // probably something hilarious going on and we're already failing at all the - // things, but at least we're going to be sound. - Edge use = m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]; - switch (node.indexingType()) { - case ALL_BLANK_INDEXING_TYPES: - case ALL_UNDECIDED_INDEXING_TYPES: - CRASH(); - break; - case ALL_DOUBLE_INDEXING_TYPES: { - SpeculateDoubleOperand operand(this, use); - GPRTemporary scratch(this); - FPRReg opFPR = operand.fpr(); - GPRReg scratchGPR = scratch.gpr(); - if (!isRealNumberSpeculation(m_state.forNode(use).m_type)) { - // FIXME: We need a way of profiling these, and we need to hoist them into - // SpeculateDoubleOperand. - speculationCheck( - BadType, JSValueRegs(), NoNode, - m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR)); - } - - m_jit.boxDouble(opFPR, scratchGPR); - m_jit.store64(scratchGPR, buffer + operandIdx); - break; - } - case ALL_INT32_INDEXING_TYPES: { - JSValueOperand operand(this, use); - GPRReg opGPR = operand.gpr(); - if (hasInt32(node.indexingType()) && !isInt32Speculation(m_state.forNode(use).m_type)) { - speculationCheck( - BadType, JSValueRegs(opGPR), use.index(), - m_jit.branch64(MacroAssembler::Below, opGPR, GPRInfo::tagTypeNumberRegister)); - } - m_jit.store64(opGPR, buffer + operandIdx); - break; - } - case ALL_CONTIGUOUS_INDEXING_TYPES: - case ALL_ARRAY_STORAGE_INDEXING_TYPES: { - JSValueOperand operand(this, use); - GPRReg opGPR = operand.gpr(); - m_jit.store64(opGPR, buffer + operandIdx); - operand.use(); - break; - } - default: - CRASH(); - break; - } - } - - switch (node.indexingType()) { - case ALL_DOUBLE_INDEXING_TYPES: - case ALL_INT32_INDEXING_TYPES: - useChildren(node); - break; - default: - break; + JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]); + GPRReg opGPR = operand.gpr(); + operand.use(); + + m_jit.store64(opGPR, buffer + operandIdx); } flushRegisters(); @@ -3634,7 +3406,7 @@ void SpeculativeJIT::compile(Node& node) GPRResult result(this); callOperation( - operationNewArray, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()), + operationNewArray, result.gpr(), globalObject->arrayStructure(), static_cast<void*>(buffer), node.numChildren()); if (scratchSize) { @@ -3650,26 +3422,18 @@ void SpeculativeJIT::compile(Node& node) case NewArrayWithSize: { JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node.codeOrigin); - if (!globalObject->isHavingABadTime() && !hasArrayStorage(node.indexingType())) { + if (!globalObject->isHavingABadTime()) { globalObject->havingABadTimeWatchpoint()->add(speculationWatchpoint()); SpeculateStrictInt32Operand size(this, node.child1()); GPRTemporary result(this); GPRTemporary storage(this); GPRTemporary scratch(this); - GPRTemporary scratch2; GPRReg sizeGPR = size.gpr(); GPRReg resultGPR = result.gpr(); GPRReg storageGPR = storage.gpr(); GPRReg scratchGPR = scratch.gpr(); - GPRReg scratch2GPR = InvalidGPRReg; - - if (hasDouble(node.indexingType())) { - GPRTemporary realScratch2(this, size); - scratch2.adopt(realScratch2); - scratch2GPR = scratch2.gpr(); - } MacroAssembler::JumpList slowCases; slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_SPARSE_ARRAY_INDEX))); @@ -3682,28 +3446,17 @@ void SpeculativeJIT::compile(Node& node) emitAllocateBasicStorage(resultGPR, storageGPR)); m_jit.subPtr(scratchGPR, storageGPR); emitAllocateBasicJSObject<JSArray, MarkedBlock::None>( - TrustedImmPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType())), resultGPR, scratchGPR, + TrustedImmPtr(globalObject->arrayStructure()), resultGPR, scratchGPR, storageGPR, sizeof(JSArray), slowCases); m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength())); - if (hasDouble(node.indexingType())) { - m_jit.move(TrustedImm64(bitwise_cast<int64_t>(QNaN)), scratchGPR); - m_jit.move(sizeGPR, scratch2GPR); - MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, scratch2GPR); - MacroAssembler::Label loop = m_jit.label(); - m_jit.sub32(TrustedImm32(1), scratch2GPR); - m_jit.store64(scratchGPR, MacroAssembler::BaseIndex(storageGPR, scratch2GPR, MacroAssembler::TimesEight)); - m_jit.branchTest32(MacroAssembler::NonZero, scratch2GPR).linkTo(loop, &m_jit); - done.link(&m_jit); - } - addSlowPathGenerator(adoptPtr( new CallArrayAllocatorWithVariableSizeSlowPathGenerator( slowCases, this, operationNewArrayWithSize, resultGPR, - globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()), - globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage), + globalObject->arrayStructure(), + globalObject->arrayStructureWithArrayStorage(), sizeGPR))); cellResult(resultGPR, m_compileIndex); @@ -3717,10 +3470,10 @@ void SpeculativeJIT::compile(Node& node) GPRReg resultGPR = result.gpr(); GPRReg structureGPR = selectScratchGPR(sizeGPR); MacroAssembler::Jump bigLength = m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_SPARSE_ARRAY_INDEX)); - m_jit.move(TrustedImmPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType())), structureGPR); + m_jit.move(TrustedImmPtr(globalObject->arrayStructure()), structureGPR); MacroAssembler::Jump done = m_jit.jump(); bigLength.link(&m_jit); - m_jit.move(TrustedImmPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)), structureGPR); + m_jit.move(TrustedImmPtr(globalObject->arrayStructureWithArrayStorage()), structureGPR); done.link(&m_jit); callOperation(operationNewArrayWithSize, resultGPR, structureGPR, sizeGPR); cellResult(resultGPR, m_compileIndex); @@ -3767,8 +3520,7 @@ void SpeculativeJIT::compile(Node& node) case NewArrayBuffer: { JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node.codeOrigin); - IndexingType indexingType = node.indexingType(); - if (!globalObject->isHavingABadTime() && !hasArrayStorage(indexingType)) { + if (!globalObject->isHavingABadTime()) { globalObject->havingABadTimeWatchpoint()->add(speculationWatchpoint()); unsigned numElements = node.numConstants(); @@ -3779,23 +3531,13 @@ void SpeculativeJIT::compile(Node& node) GPRReg resultGPR = result.gpr(); GPRReg storageGPR = storage.gpr(); - emitAllocateJSArray(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType), resultGPR, storageGPR, numElements); + emitAllocateJSArray(globalObject->arrayStructure(), resultGPR, storageGPR, numElements); - ASSERT(indexingType & IsArray); JSValue* data = m_jit.codeBlock()->constantBuffer(node.startConstant()); - if (indexingType == ArrayWithDouble) { - for (unsigned index = 0; index < node.numConstants(); ++index) { - double value = data[index].asNumber(); - m_jit.store64( - Imm64(bitwise_cast<int64_t>(value)), - MacroAssembler::Address(storageGPR, sizeof(double) * index)); - } - } else { - for (unsigned index = 0; index < node.numConstants(); ++index) { - m_jit.store64( - Imm64(JSValue::encode(data[index])), - MacroAssembler::Address(storageGPR, sizeof(JSValue) * index)); - } + for (unsigned index = 0; index < node.numConstants(); ++index) { + m_jit.store64( + Imm64(JSValue::encode(data[index])), + MacroAssembler::Address(storageGPR, sizeof(JSValue) * index)); } cellResult(resultGPR, m_compileIndex); @@ -3805,7 +3547,7 @@ void SpeculativeJIT::compile(Node& node) flushRegisters(); GPRResult result(this); - callOperation(operationNewArrayBuffer, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()), node.startConstant(), node.numConstants()); + callOperation(operationNewArrayBuffer, result.gpr(), globalObject->arrayStructure(), node.startConstant(), node.numConstants()); cellResult(result.gpr(), m_compileIndex); break; |