X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/93a3786624b2768d89bfa27e46598dc64e2fb70a..40a37d088818fc2fbeba2ef850dbcaaf294befbf:/bytecompiler/NodesCodegen.cpp?ds=inline diff --git a/bytecompiler/NodesCodegen.cpp b/bytecompiler/NodesCodegen.cpp index e3a3d26..0e81cfa 100644 --- a/bytecompiler/NodesCodegen.cpp +++ b/bytecompiler/NodesCodegen.cpp @@ -28,6 +28,7 @@ #include "Nodes.h" #include "NodeConstructors.h" +#include "BuiltinNames.h" #include "BytecodeGenerator.h" #include "CallFrame.h" #include "Debugger.h" @@ -35,14 +36,16 @@ #include "JSFunction.h" #include "JSGlobalObject.h" #include "JSNameScope.h" +#include "JSONObject.h" #include "LabelScope.h" #include "Lexer.h" -#include "Operations.h" +#include "JSCInlines.h" #include "Parser.h" #include "PropertyNameArray.h" #include "RegExpCache.h" #include "RegExpObject.h" #include "SamplingTool.h" +#include "StackAlignment.h" #include #include #include @@ -87,7 +90,7 @@ void ExpressionNode::emitBytecodeInConditionContext(BytecodeGenerator& generator RegisterID* ThrowableExpressionData::emitThrowReferenceError(BytecodeGenerator& generator, const String& message) { - generator.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart()); + generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); generator.emitThrowReferenceError(message); return generator.newTemporary(); } @@ -141,21 +144,21 @@ RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst bool ResolveNode::isPure(BytecodeGenerator& generator) const { - return generator.resolve(m_ident).isStatic(); + return generator.local(m_ident).get(); } RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - ResolveResult resolveResult = generator.resolve(m_ident); - if (RegisterID* local = resolveResult.local()) { + if (Local local = generator.local(m_ident)) { if (dst == generator.ignoredResult()) return 0; - return generator.moveToDestinationIfNeeded(dst, local); + return generator.moveToDestinationIfNeeded(dst, local.get()); } - unsigned divot = m_startOffset + m_ident.length(); - generator.emitExpressionInfo(divot, m_ident.length(), 0, m_divotLine, m_divotLineStart); - return generator.emitResolve(generator.finalDestination(dst), resolveResult, m_ident); + JSTextPosition divot = m_start + m_ident.length(); + generator.emitExpressionInfo(divot, m_start, divot); + RefPtr scope = generator.emitResolveScope(generator.tempDestination(dst), m_ident); + return generator.emitGetFromScope(generator.finalDestination(dst), scope.get(), m_ident, ThrowIfNotFound); } // ------------------------------ ArrayNode ------------------------------------ @@ -167,7 +170,7 @@ RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds unsigned length = 0; ElementNode* firstPutElement; for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) { - if (firstPutElement->elision()) + if (firstPutElement->elision() || firstPutElement->value()->isSpreadExpression()) break; ++length; } @@ -176,8 +179,10 @@ RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds return generator.emitNewArray(generator.finalDestination(dst), m_element, length); RefPtr array = generator.emitNewArray(generator.tempDestination(dst), m_element, length); - - for (ElementNode* n = firstPutElement; n; n = n->next()) { + ElementNode* n = firstPutElement; + for (; n; n = n->next()) { + if (n->value()->isSpreadExpression()) + goto handleSpread; RegisterID* value = generator.emitNode(n->value()); length += n->elision(); generator.emitPutByIndex(array.get(), length++, value); @@ -189,6 +194,31 @@ RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds } return generator.moveToDestinationIfNeeded(dst, array.get()); + +handleSpread: + RefPtr index = generator.emitLoad(generator.newTemporary(), jsNumber(length)); + auto spreader = [this, array, index](BytecodeGenerator& generator, RegisterID* value) + { + generator.emitDirectPutByVal(array.get(), index.get(), value); + generator.emitInc(index.get()); + }; + for (; n; n = n->next()) { + if (n->elision()) + generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(n->elision())), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32())); + if (n->value()->isSpreadExpression()) { + SpreadExpressionNode* spread = static_cast(n->value()); + generator.emitEnumeration(spread, spread->expression(), spreader); + } else { + generator.emitDirectPutByVal(array.get(), index.get(), generator.emitNode(n->value())); + generator.emitInc(index.get()); + } + } + + if (m_elision) { + generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(m_elision)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32())); + generator.emitPutById(array.get(), generator.propertyNames().length, index.get()); + } + return generator.moveToDestinationIfNeeded(dst, array.get()); } bool ArrayNode::isSimpleArray() const @@ -243,8 +273,14 @@ RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, Registe // Fast case: this loop just handles regular value properties. PropertyListNode* p = this; - for (; p && p->m_node->m_type == PropertyNode::Constant; p = p->m_next) - generator.emitDirectPutById(newObj.get(), p->m_node->name(), generator.emitNode(p->m_node->m_assign)); + for (; p && p->m_node->m_type == PropertyNode::Constant; p = p->m_next) { + if (p->m_node->m_name) { + generator.emitDirectPutById(newObj.get(), *p->m_node->name(), generator.emitNode(p->m_node->m_assign)); + continue; + } + RefPtr propertyName = generator.emitNode(p->m_node->m_expression); + generator.emitDirectPutByVal(newObj.get(), propertyName.get(), generator.emitNode(p->m_node->m_assign)); + } // Were there any get/set properties? if (p) { @@ -259,7 +295,7 @@ RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, Registe continue; GetterSetterPair pair(node, static_cast(0)); - GetterSetterMap::AddResult result = map.add(node->name().impl(), pair); + GetterSetterMap::AddResult result = map.add(node->name()->impl(), pair); if (!result.isNewEntry) result.iterator->value.second = node; } @@ -267,17 +303,23 @@ RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, Registe // Iterate over the remaining properties in the list. for (; p; p = p->m_next) { PropertyNode* node = p->m_node; - RegisterID* value = generator.emitNode(node->m_assign); // Handle regular values. if (node->m_type == PropertyNode::Constant) { - generator.emitDirectPutById(newObj.get(), node->name(), value); + if (node->name()) { + generator.emitDirectPutById(newObj.get(), *node->name(), generator.emitNode(node->m_assign)); + continue; + } + RefPtr propertyName = generator.emitNode(p->m_node->m_expression); + generator.emitDirectPutByVal(newObj.get(), propertyName.get(), generator.emitNode(p->m_node->m_assign)); continue; } + + RegisterID* value = generator.emitNode(node->m_assign); // This is a get/set property, find its entry in the map. ASSERT(node->m_type == PropertyNode::Getter || node->m_type == PropertyNode::Setter); - GetterSetterMap::iterator it = map.find(node->name().impl()); + GetterSetterMap::iterator it = map.find(node->name()->impl()); ASSERT(it != map.end()); GetterSetterPair& pair = it->value; @@ -310,7 +352,7 @@ RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, Registe } } - generator.emitPutGetterSetter(newObj.get(), node->name(), getterReg.get(), setterReg.get()); + generator.emitPutGetterSetter(newObj.get(), *node->name(), getterReg.get(), setterReg.get()); } } @@ -324,14 +366,14 @@ RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, Regi if (m_base->isResolveNode() && generator.willResolveToArguments(static_cast(m_base)->identifier()) && !generator.symbolTable().slowArguments()) { - RegisterID* property = generator.emitNode(m_subscript); - generator.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart()); - return generator.emitGetArgumentByVal(generator.finalDestination(dst), generator.uncheckedRegisterForArguments(), property); + RefPtr property = generator.emitNode(m_subscript); + generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); + return generator.emitGetArgumentByVal(generator.finalDestination(dst), generator.uncheckedRegisterForArguments(), property.get()); } RefPtr base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator)); RegisterID* property = generator.emitNode(m_subscript); - generator.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart()); + generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property); } @@ -345,14 +387,14 @@ RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, Register ResolveNode* resolveNode = static_cast(m_base); if (!generator.willResolveToArguments(resolveNode->identifier())) goto nonArgumentsPath; - generator.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart()); + generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); return generator.emitGetArgumentsLength(generator.finalDestination(dst), generator.uncheckedRegisterForArguments()); } nonArgumentsPath: - RegisterID* base = generator.emitNode(m_base); - generator.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart()); - return generator.emitGetById(generator.finalDestination(dst), base, m_ident); + RefPtr base = generator.emitNode(m_base); + generator.emitExpressionInfo(divot(), divotStart(), divotEnd()); + return generator.emitGetById(generator.finalDestination(dst), base.get(), m_ident); } // ------------------------------ ArgumentListNode ----------------------------- @@ -373,17 +415,19 @@ RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* else expectedFunction = NoExpectedFunction; RefPtr func = generator.emitNode(m_expr); + RefPtr returnValue = generator.finalDestination(dst, func.get()); CallArguments callArguments(generator, m_args); - return generator.emitConstruct(generator.finalDestinationOrIgnored(dst), func.get(), expectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart()); + return generator.emitConstruct(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd()); } -inline CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode) +CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode, unsigned additionalArguments) : m_argumentsNode(argumentsNode) + , m_padding(0) { if (generator.shouldEmitProfileHooks()) m_profileHookRegister = generator.newTemporary(); - size_t argumentCountIncludingThis = 1; // 'this' register. + size_t argumentCountIncludingThis = 1 + additionalArguments; // 'this' register. if (argumentsNode) { for (ArgumentListNode* node = argumentsNode->m_listNode; node; node = node->m_next) ++argumentCountIncludingThis; @@ -392,26 +436,33 @@ inline CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* m_argv.grow(argumentCountIncludingThis); for (int i = argumentCountIncludingThis - 1; i >= 0; --i) { m_argv[i] = generator.newTemporary(); - ASSERT(static_cast(i) == m_argv.size() - 1 || m_argv[i]->index() == m_argv[i + 1]->index() + 1); + ASSERT(static_cast(i) == m_argv.size() - 1 || m_argv[i]->index() == m_argv[i + 1]->index() - 1); + } + + while (stackOffset() % stackAlignmentRegisters()) { + m_argv.insert(0, generator.newTemporary()); + m_padding++; } -} - -inline void CallArguments::newArgument(BytecodeGenerator& generator) -{ - RefPtr tmp = generator.newTemporary(); - ASSERT(m_argv.isEmpty() || tmp->index() == m_argv.last()->index() + 1); // Calling convention assumes that all arguments are contiguous. - m_argv.append(tmp.release()); } // ------------------------------ EvalFunctionCallNode ---------------------------------- RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - RefPtr func = generator.tempDestination(dst); + if (Local local = generator.local(generator.propertyNames().eval)) { + RefPtr func = generator.emitMove(generator.tempDestination(dst), local.get()); + CallArguments callArguments(generator, m_args); + generator.emitLoad(callArguments.thisRegister(), jsUndefined()); + return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd()); + } + + RefPtr func = generator.newTemporary(); CallArguments callArguments(generator, m_args); - generator.emitExpressionInfo(divot() - divotStartOffset() + 4, 4, 0, divotLine(), divotLineStart()); - generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), generator.resolve(generator.propertyNames().eval), generator.propertyNames().eval); - return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart()); + JSTextPosition newDivot = divotStart() + 4; + generator.emitExpressionInfo(newDivot, divotStart(), newDivot); + generator.emitResolveScope(callArguments.thisRegister(), generator.propertyNames().eval); + generator.emitGetFromScope(func.get(), callArguments.thisRegister(), generator.propertyNames().eval, ThrowIfNotFound); + return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd()); } // ------------------------------ FunctionCallValueNode ---------------------------------- @@ -419,9 +470,10 @@ RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, Reg RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr func = generator.emitNode(m_expr); + RefPtr returnValue = generator.finalDestination(dst, func.get()); CallArguments callArguments(generator, m_args); generator.emitLoad(callArguments.thisRegister(), jsUndefined()); - return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart()); + return generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd()); } // ------------------------------ FunctionCallResolveNode ---------------------------------- @@ -429,32 +481,26 @@ RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, Re RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { ExpectedFunction expectedFunction = generator.expectedFunctionForIdentifier(m_ident); - ResolveResult resolveResult = generator.resolve(m_ident); - if (RegisterID* local = resolveResult.local()) { - RefPtr func = generator.emitMove(generator.tempDestination(dst), local); + if (Local local = generator.local(m_ident)) { + RefPtr func = generator.emitMove(generator.tempDestination(dst), local.get()); + RefPtr returnValue = generator.finalDestination(dst, func.get()); CallArguments callArguments(generator, m_args); generator.emitLoad(callArguments.thisRegister(), jsUndefined()); // This passes NoExpectedFunction because we expect that if the function is in a // local variable, then it's not one of our built-in constructors. - return generator.emitCall(generator.finalDestinationOrIgnored(dst, callArguments.thisRegister()), func.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart()); - } - - if (resolveResult.isStatic()) { - RefPtr func = generator.newTemporary(); - CallArguments callArguments(generator, m_args); - generator.emitGetStaticVar(func.get(), resolveResult, m_ident); - generator.emitLoad(callArguments.thisRegister(), jsUndefined()); - return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), expectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart()); + return generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd()); } RefPtr func = generator.newTemporary(); + RefPtr returnValue = generator.finalDestination(dst, func.get()); CallArguments callArguments(generator, m_args); - int identifierStart = divot() - divotStartOffset(); - generator.emitExpressionInfo(identifierStart + m_ident.length(), m_ident.length(), 0, divotLine(), divotLineStart()); - generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), resolveResult, m_ident); - return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), expectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart()); + JSTextPosition newDivot = divotStart() + m_ident.length(); + generator.emitExpressionInfo(newDivot, divotStart(), newDivot); + generator.emitResolveScope(callArguments.thisRegister(), m_ident); + generator.emitGetFromScope(func.get(), callArguments.thisRegister(), m_ident, ThrowIfNotFound); + return generator.emitCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd()); } // ------------------------------ FunctionCallBracketNode ---------------------------------- @@ -462,12 +508,13 @@ RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr base = generator.emitNode(m_base); - RegisterID* property = generator.emitNode(m_subscript); - generator.emitExpressionInfo(subexpressionDivot(), subexpressionStartOffset(), subexpressionEndOffset(), subexpressionLine(), subexpressionLineStart()); - RefPtr function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property); + RefPtr property = generator.emitNode(m_subscript); + generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd()); + RefPtr function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get()); + RefPtr returnValue = generator.finalDestination(dst, function.get()); CallArguments callArguments(generator, m_args); generator.emitMove(callArguments.thisRegister(), base.get()); - return generator.emitCall(generator.finalDestinationOrIgnored(dst, function.get()), function.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart()); + return generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd()); } // ------------------------------ FunctionCallDotNode ---------------------------------- @@ -475,11 +522,23 @@ RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr function = generator.tempDestination(dst); + RefPtr returnValue = generator.finalDestination(dst, function.get()); CallArguments callArguments(generator, m_args); generator.emitNode(callArguments.thisRegister(), m_base); - generator.emitExpressionInfo(subexpressionDivot(), subexpressionStartOffset(), subexpressionEndOffset(), subexpressionLine(), subexpressionLineStart()); + generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd()); generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident); - return generator.emitCall(generator.finalDestinationOrIgnored(dst, function.get()), function.get(), NoExpectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart()); + return generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd()); +} + +static RegisterID* getArgumentByVal(BytecodeGenerator& generator, ExpressionNode* base, RegisterID* property, RegisterID* dst, JSTextPosition divot, JSTextPosition divotStart, JSTextPosition divotEnd) +{ + if (base->isResolveNode() + && generator.willResolveToArguments(static_cast(base)->identifier()) + && !generator.symbolTable().slowArguments()) { + generator.emitExpressionInfo(divot, divotStart, divotEnd); + return generator.emitGetArgumentByVal(generator.finalDestination(dst), generator.uncheckedRegisterForArguments(), property); + } + return nullptr; } RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) @@ -487,38 +546,58 @@ RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RefPtr