diff options
Diffstat (limited to 'JavaScriptCore/bytecompiler')
| -rw-r--r-- | JavaScriptCore/bytecompiler/BytecodeGenerator.cpp | 113 | ||||
| -rw-r--r-- | JavaScriptCore/bytecompiler/BytecodeGenerator.h | 32 | ||||
| -rw-r--r-- | JavaScriptCore/bytecompiler/NodesCodegen.cpp | 164 |
3 files changed, 162 insertions, 147 deletions
diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp index bebfdbb..777e1e6 100644 --- a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp +++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp @@ -357,16 +357,15 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug FunctionParameters& parameters = *functionBody->parameters(); size_t parameterCount = parameters.size(); - m_nextParameterIndex = -RegisterFile::CallFrameHeaderSize - parameterCount - 1; + int nextParameterIndex = -RegisterFile::CallFrameHeaderSize - parameterCount - 1; m_parameters.grow(1 + parameterCount); // reserve space for "this" // Add "this" as a parameter - m_thisRegister.setIndex(m_nextParameterIndex); - ++m_nextParameterIndex; + m_thisRegister.setIndex(nextParameterIndex); ++m_codeBlock->m_numParameters; for (size_t i = 0; i < parameterCount; ++i) - addParameter(parameters[i]); + addParameter(parameters[i], ++nextParameterIndex); preserveLastVar(); @@ -431,23 +430,19 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugge preserveLastVar(); } -RegisterID* BytecodeGenerator::addParameter(const Identifier& ident) +void BytecodeGenerator::addParameter(const Identifier& ident, int parameterIndex) { // Parameters overwrite var declarations, but not function declarations. - RegisterID* result = 0; UString::Rep* rep = ident.ustring().rep(); if (!m_functions.contains(rep)) { - symbolTable().set(rep, m_nextParameterIndex); - RegisterID& parameter = registerFor(m_nextParameterIndex); - parameter.setIndex(m_nextParameterIndex); - result = ¶meter; + symbolTable().set(rep, parameterIndex); + RegisterID& parameter = registerFor(parameterIndex); + parameter.setIndex(parameterIndex); } // To maintain the calling convention, we have to allocate unique space for // each parameter, even if the parameter doesn't make it into the symbol table. - ++m_nextParameterIndex; ++m_codeBlock->m_numParameters; - return result; } RegisterID* BytecodeGenerator::registerFor(const Identifier& ident) @@ -1415,9 +1410,9 @@ RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExp return r0; } -RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset) +RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, CallArguments& callArguments, unsigned divot, unsigned startOffset, unsigned endOffset) { - return emitCall(op_call, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset); + return emitCall(op_call, dst, func, callArguments, divot, startOffset, endOffset); } void BytecodeGenerator::createArgumentsIfNecessary() @@ -1430,40 +1425,23 @@ void BytecodeGenerator::createArgumentsIfNecessary() instructions().append(m_codeBlock->argumentsRegister()); } -RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset) +RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, CallArguments& callArguments, unsigned divot, unsigned startOffset, unsigned endOffset) { - return emitCall(op_call_eval, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset); + return emitCall(op_call_eval, dst, func, callArguments, divot, startOffset, endOffset); } -RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset) +RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, RegisterID* func, CallArguments& callArguments, unsigned divot, unsigned startOffset, unsigned endOffset) { ASSERT(opcodeID == op_call || opcodeID == op_call_eval); ASSERT(func->refCount()); - ASSERT(thisRegister->refCount()); - RegisterID* originalFunc = func; - if (m_shouldEmitProfileHooks) { - // If codegen decided to recycle func as this call's destination register, - // we need to undo that optimization here so that func will still be around - // for the sake of op_profile_did_call. - if (dst == func) { - RefPtr<RegisterID> movedThisRegister = emitMove(newTemporary(), thisRegister); - RefPtr<RegisterID> movedFunc = emitMove(thisRegister, func); - - thisRegister = movedThisRegister.release().releaseRef(); - func = movedFunc.release().releaseRef(); - } - } + if (m_shouldEmitProfileHooks) + emitMove(callArguments.profileHookRegister(), func); // Generate code for arguments. - Vector<RefPtr<RegisterID>, 16> argv; - argv.append(thisRegister); - for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next) { - argv.append(newTemporary()); - // op_call requires the arguments to be a sequential range of registers - ASSERT(argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() + 1); - emitNode(argv.last().get(), n); - } + unsigned argumentIndex = 0; + for (ArgumentListNode* n = callArguments.argumentsNode()->m_listNode; n; n = n->m_next) + emitNode(callArguments.argumentRegister(argumentIndex++), n); // Reserve space for call frame. Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame; @@ -1472,10 +1450,10 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi if (m_shouldEmitProfileHooks) { emitOpcode(op_profile_will_call); - instructions().append(func->index()); + instructions().append(callArguments.profileHookRegister()->index()); #if ENABLE(JIT) - m_codeBlock->addFunctionRegisterInfo(instructions().size(), func->index()); + m_codeBlock->addFunctionRegisterInfo(instructions().size(), callArguments.profileHookRegister()->index()); #endif } @@ -1488,8 +1466,8 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi // Emit call. emitOpcode(opcodeID); instructions().append(func->index()); // func - instructions().append(argv.size()); // argCount - instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset + instructions().append(callArguments.count()); // argCount + instructions().append(callArguments.callFrame()); // registerOffset if (dst != ignoredResult()) { emitOpcode(op_call_put_result); instructions().append(dst->index()); // dst @@ -1497,12 +1475,7 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi if (m_shouldEmitProfileHooks) { emitOpcode(op_profile_did_call); - instructions().append(func->index()); - - if (dst == originalFunc) { - thisRegister->deref(); - func->deref(); - } + instructions().append(callArguments.profileHookRegister()->index()); } return dst; @@ -1579,34 +1552,23 @@ RegisterID* BytecodeGenerator::emitUnaryNoDstOp(OpcodeID opcodeID, RegisterID* s return src; } -RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset) +RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, CallArguments& callArguments, unsigned divot, unsigned startOffset, unsigned endOffset) { ASSERT(func->refCount()); - RegisterID* originalFunc = func; - if (m_shouldEmitProfileHooks) { - // If codegen decided to recycle func as this call's destination register, - // we need to undo that optimization here so that func will still be around - // for the sake of op_profile_did_call. - if (dst == func) { - RefPtr<RegisterID> movedFunc = emitMove(newTemporary(), func); - func = movedFunc.release().releaseRef(); - } - } + if (m_shouldEmitProfileHooks) + emitMove(callArguments.profileHookRegister(), func); // Generate code for arguments. - Vector<RefPtr<RegisterID>, 16> argv; - argv.append(newTemporary()); // reserve space for "this" - for (ArgumentListNode* n = argumentsNode ? argumentsNode->m_listNode : 0; n; n = n->m_next) { - argv.append(newTemporary()); - // op_construct requires the arguments to be a sequential range of registers - ASSERT(argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() + 1); - emitNode(argv.last().get(), n); + unsigned argumentIndex = 0; + if (ArgumentsNode* argumentsNode = callArguments.argumentsNode()) { + for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next) + emitNode(callArguments.argumentRegister(argumentIndex++), n); } if (m_shouldEmitProfileHooks) { emitOpcode(op_profile_will_call); - instructions().append(func->index()); + instructions().append(callArguments.profileHookRegister()->index()); } // Reserve space for call frame. @@ -1622,8 +1584,8 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, emitOpcode(op_construct); instructions().append(func->index()); // func - instructions().append(argv.size()); // argCount - instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset + instructions().append(callArguments.count()); // argCount + instructions().append(callArguments.callFrame()); // registerOffset if (dst != ignoredResult()) { emitOpcode(op_call_put_result); instructions().append(dst->index()); // dst @@ -1631,10 +1593,7 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, if (m_shouldEmitProfileHooks) { emitOpcode(op_profile_did_call); - instructions().append(func->index()); - - if (dst == originalFunc) - func->deref(); + instructions().append(callArguments.profileHookRegister()->index()); } return dst; @@ -1895,11 +1854,11 @@ RegisterID* BytecodeGenerator::emitCatch(RegisterID* targetRegister, Label* star return targetRegister; } -RegisterID* BytecodeGenerator::emitNewError(RegisterID* dst, ErrorType type, JSValue message) +RegisterID* BytecodeGenerator::emitNewError(RegisterID* dst, bool isReferenceError, JSValue message) { emitOpcode(op_new_error); instructions().append(dst->index()); - instructions().append(static_cast<int>(type)); + instructions().append(isReferenceError); instructions().append(addConstantValue(message)->index()); return dst; } @@ -2056,7 +2015,7 @@ RegisterID* BytecodeGenerator::emitThrowExpressionTooDeepException() // that from an arbitrary node. However, calling emitExpressionInfo without any useful data // is still good enough to get us an accurate line number. emitExpressionInfo(0, 0, 0); - RegisterID* exception = emitNewError(newTemporary(), SyntaxError, jsString(globalData(), "Expression too deep")); + RegisterID* exception = emitNewError(newTemporary(), false, jsString(globalData(), "Expression too deep")); emitThrow(exception); return exception; } diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/JavaScriptCore/bytecompiler/BytecodeGenerator.h index 398d666..8f0ce34 100644 --- a/JavaScriptCore/bytecompiler/BytecodeGenerator.h +++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.h @@ -51,6 +51,23 @@ namespace JSC { class ScopeChain; class ScopeNode; + class CallArguments { + public: + CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode); + + RegisterID* thisRegister() { return m_argv[0].get(); } + RegisterID* argumentRegister(unsigned i) { return m_argv[i + 1].get(); } + unsigned callFrame() { return thisRegister()->index() + count() + RegisterFile::CallFrameHeaderSize; } + unsigned count() { return m_argv.size(); } + RegisterID* profileHookRegister() { return m_profileHookRegister.get(); } + ArgumentsNode* argumentsNode() { return m_argumentsNode; } + + private: + RefPtr<RegisterID> m_profileHookRegister; + ArgumentsNode* m_argumentsNode; + Vector<RefPtr<RegisterID>, 16> m_argv; + }; + struct FinallyContext { Label* finallyAddr; RegisterID* retAddrDst; @@ -319,15 +336,15 @@ namespace JSC { RegisterID* emitPutGetter(RegisterID* base, const Identifier& property, RegisterID* value); RegisterID* emitPutSetter(RegisterID* base, const Identifier& property, RegisterID* value); - RegisterID* emitCall(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); - RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + RegisterID* emitCall(RegisterID* dst, RegisterID* func, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset); + RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset); RegisterID* emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* argCount, unsigned divot, unsigned startOffset, unsigned endOffset); RegisterID* emitLoadVarargs(RegisterID* argCountDst, RegisterID* args); RegisterID* emitReturn(RegisterID* src); RegisterID* emitEnd(RegisterID* src) { return emitUnaryNoDstOp(op_end, src); } - RegisterID* emitConstruct(RegisterID* dst, RegisterID* func, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + RegisterID* emitConstruct(RegisterID* dst, RegisterID* func, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset); RegisterID* emitStrcat(RegisterID* dst, RegisterID* src, int count); void emitToPrimitive(RegisterID* dst, RegisterID* src); @@ -347,7 +364,7 @@ namespace JSC { RegisterID* emitCatch(RegisterID*, Label* start, Label* end); void emitThrow(RegisterID* exc) { emitUnaryNoDstOp(op_throw, exc); } - RegisterID* emitNewError(RegisterID* dst, ErrorType type, JSValue message); + RegisterID* emitNewError(RegisterID* dst, bool isReferenceError, JSValue message); void emitPushNewScope(RegisterID* dst, const Identifier& property, RegisterID* value); RegisterID* emitPushScope(RegisterID* scope); @@ -386,6 +403,8 @@ namespace JSC { m_codeBlockBeingRegeneratedFrom = originalCodeBlock; } + bool shouldEmitProfileHooks() { return m_shouldEmitProfileHooks; } + private: void emitOpcode(OpcodeID); void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index); @@ -410,7 +429,7 @@ namespace JSC { typedef HashMap<double, JSValue> NumberMap; typedef HashMap<UString::Rep*, JSString*, IdentifierRepHash> IdentifierStringMap; - RegisterID* emitCall(OpcodeID, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + RegisterID* emitCall(OpcodeID, RegisterID* dst, RegisterID* func, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset); RegisterID* newRegister(); @@ -442,7 +461,7 @@ namespace JSC { // Returns true if a new RegisterID was added, false if a pre-existing RegisterID was re-used. bool addGlobalVar(const Identifier&, bool isConstant, RegisterID*&); - RegisterID* addParameter(const Identifier&); + void addParameter(const Identifier&, int parameterIndex); void preserveLastVar(); @@ -515,7 +534,6 @@ namespace JSC { Vector<ForInContext> m_forInContextStack; int m_nextGlobalIndex; - int m_nextParameterIndex; int m_firstConstantIndex; int m_nextConstantOffset; unsigned m_globalConstantIndex; diff --git a/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/JavaScriptCore/bytecompiler/NodesCodegen.cpp index c514b7a..765230e 100644 --- a/JavaScriptCore/bytecompiler/NodesCodegen.cpp +++ b/JavaScriptCore/bytecompiler/NodesCodegen.cpp @@ -81,27 +81,27 @@ static void substitute(UString& string, const UString& substring) string = makeString(string.substr(0, position), substring, string.substr(position + 2)); } -RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* message) +RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, bool isReferenceError, const char* message) { generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - RegisterID* exception = generator.emitNewError(generator.newTemporary(), type, jsString(generator.globalData(), message)); + RegisterID* exception = generator.emitNewError(generator.newTemporary(), isReferenceError, jsString(generator.globalData(), message)); generator.emitThrow(exception); return exception; } -RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* messageTemplate, const UString& label) +RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, bool isReferenceError, const char* messageTemplate, const UString& label) { UString message = messageTemplate; substitute(message, label); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - RegisterID* exception = generator.emitNewError(generator.newTemporary(), type, jsString(generator.globalData(), message)); + RegisterID* exception = generator.emitNewError(generator.newTemporary(), isReferenceError, jsString(generator.globalData(), message)); generator.emitThrow(exception); return exception; } -inline RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* messageTemplate, const Identifier& label) +inline RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, bool isReferenceError, const char* messageTemplate, const Identifier& label) { - return emitThrowError(generator, type, messageTemplate, label.ustring()); + return emitThrowError(generator, isReferenceError, messageTemplate, label.ustring()); } // ------------------------------ NullNode ------------------------------------- @@ -146,7 +146,7 @@ RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d { RefPtr<RegExp> regExp = RegExp::create(generator.globalData(), m_pattern.ustring(), m_flags.ustring()); if (!regExp->isValid()) - return emitThrowError(generator, SyntaxError, "Invalid regular expression: %s", regExp->errorMessage()); + return emitThrowError(generator, false, "Invalid regular expression: %s", regExp->errorMessage()); if (dst == generator.ignoredResult()) return 0; return generator.emitNewRegExp(generator.finalDestination(dst), regExp.get()); @@ -316,7 +316,23 @@ RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, Registe RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> func = generator.emitNode(m_expr); - return generator.emitConstruct(generator.finalDestinationOrIgnored(dst), func.get(), m_args, divot(), startOffset(), endOffset()); + CallArguments callArguments(generator, m_args); + return generator.emitConstruct(generator.finalDestinationOrIgnored(dst), func.get(), callArguments, divot(), startOffset(), endOffset()); +} + +CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode) + : m_argumentsNode(argumentsNode) +{ + if (generator.shouldEmitProfileHooks()) + m_profileHookRegister = generator.newTemporary(); + m_argv.append(generator.newTemporary()); + if (argumentsNode) { + for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next) { + m_argv.append(generator.newTemporary()); + // op_call requires the arguments to be a sequential range of registers + ASSERT(m_argv[m_argv.size() - 1]->index() == m_argv[m_argv.size() - 2]->index() + 1); + } + } } // ------------------------------ EvalFunctionCallNode ---------------------------------- @@ -324,10 +340,10 @@ RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> func = generator.tempDestination(dst); - RefPtr<RegisterID> thisRegister = generator.newTemporary(); + CallArguments callArguments(generator, m_args); generator.emitExpressionInfo(divot() - startOffset() + 4, 4, 0); - generator.emitResolveWithBase(thisRegister.get(), func.get(), generator.propertyNames().eval); - return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); + generator.emitResolveWithBase(callArguments.thisRegister(), func.get(), generator.propertyNames().eval); + return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset()); } // ------------------------------ FunctionCallValueNode ---------------------------------- @@ -335,8 +351,9 @@ RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, Reg RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> func = generator.emitNode(m_expr); - RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); - return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); + CallArguments callArguments(generator, m_args); + generator.emitLoad(callArguments.thisRegister(), jsNull()); + return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset()); } // ------------------------------ FunctionCallResolveNode ---------------------------------- @@ -344,8 +361,9 @@ RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, Re RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) { - RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); - return generator.emitCall(generator.finalDestinationOrIgnored(dst, thisRegister.get()), local.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); + CallArguments callArguments(generator, m_args); + generator.emitLoad(callArguments.thisRegister(), jsNull()); + return generator.emitCall(generator.finalDestinationOrIgnored(dst, callArguments.thisRegister()), local.get(), callArguments, divot(), startOffset(), endOffset()); } int index = 0; @@ -354,16 +372,17 @@ RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, bool requiresDynamicChecks = false; if (generator.findScopedProperty(m_ident, index, depth, false, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) { RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject); - RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); - return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); + CallArguments callArguments(generator, m_args); + generator.emitLoad(callArguments.thisRegister(), jsNull()); + return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset()); } RefPtr<RegisterID> func = generator.newTemporary(); - RefPtr<RegisterID> thisRegister = generator.newTemporary(); + CallArguments callArguments(generator, m_args); int identifierStart = divot() - startOffset(); generator.emitExpressionInfo(identifierStart + m_ident.size(), m_ident.size(), 0); - generator.emitResolveWithBase(thisRegister.get(), func.get(), m_ident); - return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); + generator.emitResolveWithBase(callArguments.thisRegister(), func.get(), m_ident); + return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset()); } // ------------------------------ FunctionCallBracketNode ---------------------------------- @@ -374,8 +393,9 @@ RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* property = generator.emitNode(m_subscript); generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property); - RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); - return generator.emitCall(generator.finalDestinationOrIgnored(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); + CallArguments callArguments(generator, m_args); + generator.emitMove(callArguments.thisRegister(), base.get()); + return generator.emitCall(generator.finalDestinationOrIgnored(dst, function.get()), function.get(), callArguments, divot(), startOffset(), endOffset()); } // ------------------------------ FunctionCallDotNode ---------------------------------- @@ -383,12 +403,12 @@ RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { RefPtr<RegisterID> function = generator.tempDestination(dst); - RefPtr<RegisterID> thisRegister = generator.newTemporary(); - generator.emitNode(thisRegister.get(), m_base); + CallArguments callArguments(generator, m_args); + generator.emitNode(callArguments.thisRegister(), m_base); generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); generator.emitMethodCheck(); - generator.emitGetById(function.get(), thisRegister.get(), m_ident); - return generator.emitCall(generator.finalDestinationOrIgnored(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); + generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident); + return generator.emitCall(generator.finalDestinationOrIgnored(dst, function.get()), function.get(), callArguments, divot(), startOffset(), endOffset()); } RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) @@ -401,28 +421,36 @@ RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RefPtr<RegisterID> finalDestinationOrIgnored = generator.finalDestinationOrIgnored(dst, function.get()); generator.emitJumpIfNotFunctionCall(function.get(), realCall.get()); { - RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); - RefPtr<RegisterID> thisRegister = generator.newTemporary(); - ArgumentListNode* oldList = m_args->m_listNode; if (m_args->m_listNode && m_args->m_listNode->m_expr) { - generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr); + ArgumentListNode* oldList = m_args->m_listNode; m_args->m_listNode = m_args->m_listNode->m_next; - } else - generator.emitLoad(thisRegister.get(), jsNull()); - generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); - generator.emitJump(end.get()); - m_args->m_listNode = oldList; + RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); + CallArguments callArguments(generator, m_args); + generator.emitNode(callArguments.thisRegister(), oldList->m_expr); + generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset()); + generator.emitJump(end.get()); + + m_args->m_listNode = oldList; + + } else { + RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); + CallArguments callArguments(generator, m_args); + generator.emitLoad(callArguments.thisRegister(), jsNull()); + generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset()); + generator.emitJump(end.get()); + } } generator.emitLabel(realCall.get()); { - RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); - generator.emitCall(finalDestinationOrIgnored.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); + CallArguments callArguments(generator, m_args); + generator.emitMove(callArguments.thisRegister(), base.get()); + generator.emitCall(finalDestinationOrIgnored.get(), function.get(), callArguments, divot(), startOffset(), endOffset()); } generator.emitLabel(end.get()); return finalDestinationOrIgnored.get(); } - + static bool areTrivialApplyArguments(ArgumentsNode* args) { return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next @@ -445,21 +473,30 @@ RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, generator.emitJumpIfNotFunctionApply(function.get(), realCall.get()); { if (mayBeCall) { - RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); - RefPtr<RegisterID> thisRegister = generator.newTemporary(); - ArgumentListNode* oldList = m_args->m_listNode; if (m_args->m_listNode && m_args->m_listNode->m_expr) { - generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr); - m_args->m_listNode = m_args->m_listNode->m_next; - if (m_args->m_listNode) { - ASSERT(m_args->m_listNode->m_expr->isSimpleArray()); - ASSERT(!m_args->m_listNode->m_next); - m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_expr)->toArgumentList(generator.globalData()); + ArgumentListNode* oldList = m_args->m_listNode; + if (m_args->m_listNode->m_next) { + ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray()); + ASSERT(!m_args->m_listNode->m_next->m_next); + m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_next->m_expr)->toArgumentList(generator.globalData()); + RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); + CallArguments callArguments(generator, m_args); + generator.emitNode(callArguments.thisRegister(), oldList->m_expr); + generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset()); + } else { + m_args->m_listNode = m_args->m_listNode->m_next; + RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); + CallArguments callArguments(generator, m_args); + generator.emitNode(callArguments.thisRegister(), oldList->m_expr); + generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset()); } - } else - generator.emitLoad(thisRegister.get(), jsNull()); - generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); - m_args->m_listNode = oldList; + m_args->m_listNode = oldList; + } else { + RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); + CallArguments callArguments(generator, m_args); + generator.emitLoad(callArguments.thisRegister(), jsNull()); + generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset()); + } } else { ASSERT(m_args->m_listNode && m_args->m_listNode->m_next); RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get()); @@ -487,8 +524,9 @@ RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, } generator.emitLabel(realCall.get()); { - RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); - generator.emitCall(finalDestinationOrIgnored.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); + CallArguments callArguments(generator, m_args); + generator.emitMove(callArguments.thisRegister(), base.get()); + generator.emitCall(finalDestinationOrIgnored.get(), function.get(), callArguments, divot(), startOffset(), endOffset()); } generator.emitLabel(end.get()); return finalDestinationOrIgnored.get(); @@ -604,7 +642,7 @@ RegisterID* PostfixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterI RegisterID* PostfixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { - return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus + return emitThrowError(generator, true, m_operator == OpPlusPlus ? "Postfix ++ operator applied to value that is not a reference." : "Postfix -- operator applied to value that is not a reference."); } @@ -769,7 +807,7 @@ RegisterID* PrefixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID RegisterID* PrefixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { - return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus + return emitThrowError(generator, true, m_operator == OpPlusPlus ? "Prefix ++ operator applied to value that is not a reference." : "Prefix -- operator applied to value that is not a reference."); } @@ -1212,7 +1250,7 @@ RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, Regist RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) { - return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference."); + return emitThrowError(generator, true, "Left side of assignment is not a reference."); } // ------------------------------ AssignBracketNode ----------------------------------- @@ -1517,7 +1555,7 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); if (!m_lexpr->isLocation()) - return emitThrowError(generator, ReferenceError, "Left side of for-in statement is not a reference."); + return emitThrowError(generator, true, "Left side of for-in statement is not a reference."); generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); @@ -1596,8 +1634,8 @@ RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* if (!scope) return m_ident.isEmpty() - ? emitThrowError(generator, SyntaxError, "Invalid continue statement.") - : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident); + ? emitThrowError(generator, false, "Invalid continue statement.") + : emitThrowError(generator, false, "Undefined label: '%s'.", m_ident); generator.emitJumpScopes(scope->continueTarget(), scope->scopeDepth()); return dst; @@ -1614,8 +1652,8 @@ RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds if (!scope) return m_ident.isEmpty() - ? emitThrowError(generator, SyntaxError, "Invalid break statement.") - : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident); + ? emitThrowError(generator, false, "Invalid break statement.") + : emitThrowError(generator, false, "Undefined label: '%s'.", m_ident); generator.emitJumpScopes(scope->breakTarget(), scope->scopeDepth()); return dst; @@ -1627,7 +1665,7 @@ RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d { generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); if (generator.codeType() != FunctionCode) - return emitThrowError(generator, SyntaxError, "Invalid return statement."); + return emitThrowError(generator, false, "Invalid return statement."); if (dst == generator.ignoredResult()) dst = 0; @@ -1833,7 +1871,7 @@ RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); if (generator.breakTarget(m_name)) - return emitThrowError(generator, SyntaxError, "Duplicate label: %s.", m_name); + return emitThrowError(generator, false, "Duplicate label: %s.", m_name); RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name); RegisterID* r0 = generator.emitNode(dst, m_statement); |
