summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/bytecompiler
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2010-05-26 10:11:43 +0100
committerSteve Block <steveblock@google.com>2010-05-27 11:14:42 +0100
commite78cbe89e6f337f2f1fe40315be88f742b547151 (patch)
treed778000b84a04f24bbad50c7fa66244365e960e9 /JavaScriptCore/bytecompiler
parent7b582e96e4e909ed7dba1e07153d20fbddaec3f7 (diff)
downloadexternal_webkit-e78cbe89e6f337f2f1fe40315be88f742b547151.zip
external_webkit-e78cbe89e6f337f2f1fe40315be88f742b547151.tar.gz
external_webkit-e78cbe89e6f337f2f1fe40315be88f742b547151.tar.bz2
Merge WebKit at r60074: Initial merge by git
Change-Id: I18a2dc5439e36c928351ea829d8fb4e39b062fc7
Diffstat (limited to 'JavaScriptCore/bytecompiler')
-rw-r--r--JavaScriptCore/bytecompiler/BytecodeGenerator.cpp88
-rw-r--r--JavaScriptCore/bytecompiler/BytecodeGenerator.h34
-rw-r--r--JavaScriptCore/bytecompiler/NodesCodegen.cpp34
3 files changed, 96 insertions, 60 deletions
diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index e5f3d15..cdf87d2 100644
--- a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -174,8 +174,7 @@ bool BytecodeGenerator::addVar(const Identifier& ident, bool isConstant, Registe
return false;
}
- ++m_codeBlock->m_numVars;
- r0 = newRegister();
+ r0 = addVar();
return true;
}
@@ -295,6 +294,7 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug
, m_symbolTable(symbolTable)
, m_scopeNode(functionBody)
, m_codeBlock(codeBlock)
+ , m_activationRegister(0)
, m_finallyDepth(0)
, m_dynamicScopeDepth(0)
, m_baseScopeDepth(0)
@@ -312,29 +312,35 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug
codeBlock->setGlobalData(m_globalData);
- bool usesArguments = functionBody->usesArguments();
- codeBlock->setUsesArguments(usesArguments);
- if (usesArguments) {
- m_argumentsRegister.setIndex(RegisterFile::OptionalCalleeArguments);
- addVar(propertyNames().arguments, false);
- }
-
if (m_codeBlock->needsFullScopeChain()) {
- ++m_codeBlock->m_numVars;
- m_activationRegisterIndex = newRegister()->index();
+ m_activationRegister = addVar();
emitOpcode(op_enter_with_activation);
- instructions().append(m_activationRegisterIndex);
+ instructions().append(m_activationRegister->index());
} else
emitOpcode(op_enter);
- if (usesArguments) {
+ // Both op_tear_off_activation and op_tear_off_arguments tear off the 'arguments'
+ // object, if created.
+ if (m_codeBlock->needsFullScopeChain() || functionBody->usesArguments()) {
+ RegisterID* unmodifiedArgumentsRegister = addVar(); // Anonymous, so it can't be modified by user code.
+ RegisterID* argumentsRegister = addVar(propertyNames().arguments, false); // Can be changed by assigning to 'arguments'.
+
+ // We can save a little space by hard-coding the knowledge that the two
+ // 'arguments' values are stored in consecutive registers, and storing
+ // only the index of the assignable one.
+ codeBlock->setArgumentsRegister(argumentsRegister->index());
+ ASSERT_UNUSED(unmodifiedArgumentsRegister, unmodifiedArgumentsRegister->index() == JSC::unmodifiedArgumentsRegister(codeBlock->argumentsRegister()));
+
emitOpcode(op_init_arguments);
+ instructions().append(argumentsRegister->index());
// The debugger currently retrieves the arguments object from an activation rather than pulling
// it from a call frame. In the long-term it should stop doing that (<rdar://problem/6911886>),
// but for now we force eager creation of the arguments object when debugging.
- if (m_shouldEmitDebugHooks)
+ if (m_shouldEmitDebugHooks) {
emitOpcode(op_create_arguments);
+ instructions().append(argumentsRegister->index());
+ }
}
const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack();
@@ -359,7 +365,7 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug
++m_nextParameterIndex;
++m_codeBlock->m_numParameters;
- if (functionBody->usesThis() || m_shouldEmitDebugHooks) {
+ if (!isConstructor() && (functionBody->usesThis() || m_shouldEmitDebugHooks)) {
emitOpcode(op_convert_this);
instructions().append(m_thisRegister.index());
}
@@ -1025,7 +1031,7 @@ bool BytecodeGenerator::findScopedProperty(const Identifier& property, int& inde
globalObject = currentVariableObject;
return false;
}
- stackDepth = depth;
+ stackDepth = depth + m_codeBlock->needsFullScopeChain();
index = entry.getIndex();
if (++iter == end)
globalObject = currentVariableObject;
@@ -1037,7 +1043,7 @@ bool BytecodeGenerator::findScopedProperty(const Identifier& property, int& inde
requiresDynamicChecks |= scopeRequiresDynamicChecks;
}
// Can't locate the property but we're able to avoid a few lookups.
- stackDepth = depth;
+ stackDepth = depth + m_codeBlock->needsFullScopeChain();
index = missingSymbolMarker();
JSObject* scope = *iter;
if (++iter == end)
@@ -1385,7 +1391,6 @@ RegisterID* BytecodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp)
return dst;
}
-
RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNode* n)
{
FunctionBodyNode* function = n->body();
@@ -1404,13 +1409,16 @@ RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, Regis
void BytecodeGenerator::createArgumentsIfNecessary()
{
- if (m_codeBlock->usesArguments() && m_codeType == FunctionCode)
- emitOpcode(op_create_arguments);
+ if (m_codeType != FunctionCode)
+ return;
+ ASSERT(m_codeBlock->usesArguments());
+
+ emitOpcode(op_create_arguments);
+ instructions().append(m_codeBlock->argumentsRegister());
}
RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
{
- createArgumentsIfNecessary();
return emitCall(op_call_eval, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset);
}
@@ -1466,10 +1474,13 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi
// Emit call.
emitOpcode(opcodeID);
- instructions().append(dst->index()); // dst
instructions().append(func->index()); // func
instructions().append(argv.size()); // argCount
instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset
+ if (dst != ignoredResult()) {
+ emitOpcode(op_call_put_result);
+ instructions().append(dst->index()); // dst
+ }
if (m_shouldEmitProfileHooks) {
emitOpcode(op_profile_did_call);
@@ -1511,10 +1522,13 @@ RegisterID* BytecodeGenerator::emitCallVarargs(RegisterID* dst, RegisterID* func
// Emit call.
emitOpcode(op_call_varargs);
- instructions().append(dst->index()); // dst
instructions().append(func->index()); // func
instructions().append(argCountRegister->index()); // arg count
instructions().append(thisRegister->index() + RegisterFile::CallFrameHeaderSize); // initial registerOffset
+ if (dst != ignoredResult()) {
+ emitOpcode(op_call_put_result);
+ instructions().append(dst->index()); // dst
+ }
if (m_shouldEmitProfileHooks) {
emitOpcode(op_profile_did_call);
instructions().append(func->index());
@@ -1526,10 +1540,22 @@ RegisterID* BytecodeGenerator::emitReturn(RegisterID* src)
{
if (m_codeBlock->needsFullScopeChain()) {
emitOpcode(op_tear_off_activation);
- instructions().append(m_activationRegisterIndex);
- } else if (m_codeBlock->usesArguments() && m_codeBlock->m_numParameters > 1)
+ instructions().append(m_activationRegister->index());
+ instructions().append(m_codeBlock->argumentsRegister());
+ } else if (m_codeBlock->usesArguments() && m_codeBlock->m_numParameters > 1) { // If there are no named parameters, there's nothing to tear off, since extra / unnamed parameters get copied to the arguments object at construct time.
emitOpcode(op_tear_off_arguments);
+ instructions().append(m_codeBlock->argumentsRegister());
+ }
+ // Constructors use op_ret_object_or_this to check the result is an
+ // object, unless we can trivially determine the check is not
+ // necessary (currently, if the return value is 'this').
+ if (isConstructor() && (src->index() != m_thisRegister.index())) {
+ emitOpcode(op_ret_object_or_this);
+ instructions().append(src->index());
+ instructions().append(m_thisRegister.index());
+ return src;
+ }
return emitUnaryNoDstOp(op_ret, src);
}
@@ -1589,16 +1615,15 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func,
#endif
emitOpcode(op_construct);
- instructions().append(dst->index()); // dst
instructions().append(func->index()); // func
instructions().append(argv.size()); // argCount
instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset
instructions().append(funcProto->index()); // proto
instructions().append(argv[0]->index()); // thisRegister
-
- emitOpcode(op_construct_verify);
- instructions().append(dst->index());
- instructions().append(argv[0]->index());
+ if (dst != ignoredResult()) {
+ emitOpcode(op_call_put_result);
+ instructions().append(dst->index()); // dst
+ }
if (m_shouldEmitProfileHooks) {
emitOpcode(op_profile_did_call);
@@ -1635,7 +1660,6 @@ RegisterID* BytecodeGenerator::emitPushScope(RegisterID* scope)
context.isFinallyBlock = false;
m_scopeContextStack.append(context);
m_dynamicScopeDepth++;
- createArgumentsIfNecessary();
return emitUnaryNoDstOp(op_push_scope, scope);
}
@@ -1899,8 +1923,6 @@ void BytecodeGenerator::emitPushNewScope(RegisterID* dst, const Identifier& prop
context.isFinallyBlock = false;
m_scopeContextStack.append(context);
m_dynamicScopeDepth++;
-
- createArgumentsIfNecessary();
emitOpcode(op_push_new_scope);
instructions().append(dst->index());
diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/JavaScriptCore/bytecompiler/BytecodeGenerator.h
index 0a49392..7626bf4 100644
--- a/JavaScriptCore/bytecompiler/BytecodeGenerator.h
+++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.h
@@ -83,6 +83,8 @@ namespace JSC {
JSGlobalData* globalData() const { return m_globalData; }
const CommonIdentifiers& propertyNames() const { return *m_globalData->propertyNames; }
+ bool isConstructor() { return m_codeBlock->m_isConstructor; }
+
void generate();
// Returns the register corresponding to a local variable, or 0 if no
@@ -103,9 +105,6 @@ namespace JSC {
// VariableObject that defines the property. If the property cannot be found
// statically, depth will contain the depth of the scope chain where dynamic
// lookup must begin.
- //
- // NB: depth does _not_ include the local scope. eg. a depth of 0 refers
- // to the scope containing this codeblock.
bool findScopedProperty(const Identifier&, int& index, size_t& depth, bool forWriting, bool& includesDynamicScopes, JSObject*& globalObject);
// Returns the register storing "this"
@@ -150,6 +149,17 @@ namespace JSC {
return newTemporary();
}
+ // Returns the place to write the final output of an operation.
+ RegisterID* finalDestinationOrIgnored(RegisterID* originalDst, RegisterID* tempDst = 0)
+ {
+ if (originalDst)
+ return originalDst;
+ ASSERT(tempDst != ignoredResult());
+ if (tempDst && tempDst->isTemporary())
+ return tempDst;
+ return newTemporary();
+ }
+
RegisterID* destinationForAssignResult(RegisterID* dst)
{
if (dst && dst != ignoredResult() && m_codeBlock->needsFullScopeChain())
@@ -404,15 +414,23 @@ namespace JSC {
RegisterID* newRegister();
- // Returns the RegisterID corresponding to ident.
+ // Adds a var slot and maps it to the name ident in symbolTable().
RegisterID* addVar(const Identifier& ident, bool isConstant)
{
RegisterID* local;
addVar(ident, isConstant, local);
return local;
}
- // Returns true if a new RegisterID was added, false if a pre-existing RegisterID was re-used.
+
+ // Ditto. Returns true if a new RegisterID was added, false if a pre-existing RegisterID was re-used.
bool addVar(const Identifier&, bool isConstant, RegisterID*&);
+
+ // Adds an anonymous var slot. To give this slot a name, add it to symbolTable().
+ RegisterID* addVar()
+ {
+ ++m_codeBlock->m_numVars;
+ return newRegister();
+ }
// Returns the RegisterID corresponding to ident.
RegisterID* addGlobalVar(const Identifier& ident, bool isConstant)
@@ -433,9 +451,6 @@ namespace JSC {
if (index >= 0)
return m_calleeRegisters[index];
- if (index == RegisterFile::OptionalCalleeArguments)
- return m_argumentsRegister;
-
if (m_parameters.size()) {
ASSERT(!m_globals.size());
return m_parameters[index + m_parameters.size() + RegisterFile::CallFrameHeaderSize];
@@ -482,8 +497,7 @@ namespace JSC {
HashSet<RefPtr<UString::Rep>, IdentifierRepHash> m_functions;
RegisterID m_ignoredResultRegister;
RegisterID m_thisRegister;
- RegisterID m_argumentsRegister;
- int m_activationRegisterIndex;
+ RegisterID* m_activationRegister;
SegmentedVector<RegisterID, 32> m_constantPoolRegisters;
SegmentedVector<RegisterID, 32> m_calleeRegisters;
SegmentedVector<RegisterID, 32> m_parameters;
diff --git a/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/JavaScriptCore/bytecompiler/NodesCodegen.cpp
index cfd00da..c514b7a 100644
--- a/JavaScriptCore/bytecompiler/NodesCodegen.cpp
+++ b/JavaScriptCore/bytecompiler/NodesCodegen.cpp
@@ -316,7 +316,7 @@ RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, Registe
RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
RefPtr<RegisterID> func = generator.emitNode(m_expr);
- return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args, divot(), startOffset(), endOffset());
+ return generator.emitConstruct(generator.finalDestinationOrIgnored(dst), func.get(), m_args, divot(), startOffset(), endOffset());
}
// ------------------------------ EvalFunctionCallNode ----------------------------------
@@ -336,7 +336,7 @@ RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, Re
{
RefPtr<RegisterID> func = generator.emitNode(m_expr);
RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
- return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+ return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
}
// ------------------------------ FunctionCallResolveNode ----------------------------------
@@ -345,7 +345,7 @@ RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator,
{
if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) {
RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
- return generator.emitCall(generator.finalDestination(dst, thisRegister.get()), local.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+ return generator.emitCall(generator.finalDestinationOrIgnored(dst, thisRegister.get()), local.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
}
int index = 0;
@@ -355,7 +355,7 @@ RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator,
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.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+ return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
}
RefPtr<RegisterID> func = generator.newTemporary();
@@ -363,7 +363,7 @@ RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator,
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.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+ return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
}
// ------------------------------ FunctionCallBracketNode ----------------------------------
@@ -375,7 +375,7 @@ RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator,
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.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+ return generator.emitCall(generator.finalDestinationOrIgnored(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
}
// ------------------------------ FunctionCallDotNode ----------------------------------
@@ -388,7 +388,7 @@ RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, Regi
generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
generator.emitMethodCheck();
generator.emitGetById(function.get(), thisRegister.get(), m_ident);
- return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+ return generator.emitCall(generator.finalDestinationOrIgnored(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
}
RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
@@ -398,7 +398,7 @@ RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
RefPtr<RegisterID> base = generator.emitNode(m_base);
generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
- RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get());
+ RefPtr<RegisterID> finalDestinationOrIgnored = generator.finalDestinationOrIgnored(dst, function.get());
generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
{
RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
@@ -410,17 +410,17 @@ RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
} else
generator.emitLoad(thisRegister.get(), jsNull());
- generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+ generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
generator.emitJump(end.get());
m_args->m_listNode = oldList;
}
generator.emitLabel(realCall.get());
{
RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
- generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+ generator.emitCall(finalDestinationOrIgnored.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
}
generator.emitLabel(end.get());
- return finalDestination.get();
+ return finalDestinationOrIgnored.get();
}
static bool areTrivialApplyArguments(ArgumentsNode* args)
@@ -441,7 +441,7 @@ RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
RefPtr<RegisterID> base = generator.emitNode(m_base);
generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
- RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get());
+ RefPtr<RegisterID> finalDestinationOrIgnored = generator.finalDestinationOrIgnored(dst, function.get());
generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
{
if (mayBeCall) {
@@ -458,7 +458,7 @@ RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
}
} else
generator.emitLoad(thisRegister.get(), jsNull());
- generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+ generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
m_args->m_listNode = oldList;
} else {
ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
@@ -481,17 +481,17 @@ RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
generator.emitNode(args->m_expr);
generator.emitLoadVarargs(argsCountRegister.get(), argsRegister.get());
- generator.emitCallVarargs(finalDestination.get(), realFunction.get(), thisRegister.get(), argsCountRegister.get(), divot(), startOffset(), endOffset());
+ generator.emitCallVarargs(finalDestinationOrIgnored.get(), realFunction.get(), thisRegister.get(), argsCountRegister.get(), divot(), startOffset(), endOffset());
}
generator.emitJump(end.get());
}
generator.emitLabel(realCall.get());
{
RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
- generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+ generator.emitCall(finalDestinationOrIgnored.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
}
generator.emitLabel(end.get());
- return finalDestination.get();
+ return finalDestinationOrIgnored.get();
}
// ------------------------------ PostfixResolveNode ----------------------------------
@@ -1979,7 +1979,7 @@ RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, Registe
return 0;
}
- RegisterID* r0 = generator.emitLoad(0, jsUndefined());
+ RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined());
generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
generator.emitReturn(r0);
return 0;