diff options
author | Feng Qian <fqian@google.com> | 2009-06-17 12:12:20 -0700 |
---|---|---|
committer | Feng Qian <fqian@google.com> | 2009-06-17 12:12:20 -0700 |
commit | 5f1ab04193ad0130ca8204aadaceae083aca9881 (patch) | |
tree | 5a92cd389e2cfe7fb67197ce14b38469462379f8 /JavaScriptCore/bytecompiler | |
parent | 194315e5a908cc8ed67d597010544803eef1ac59 (diff) | |
download | external_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.zip external_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.tar.gz external_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.tar.bz2 |
Get WebKit r44544.
Diffstat (limited to 'JavaScriptCore/bytecompiler')
-rw-r--r-- | JavaScriptCore/bytecompiler/BytecodeGenerator.cpp | 272 | ||||
-rw-r--r-- | JavaScriptCore/bytecompiler/BytecodeGenerator.h | 38 |
2 files changed, 263 insertions, 47 deletions
diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp index c83cdc7..21a3016 100644 --- a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp +++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp @@ -31,6 +31,7 @@ #include "BytecodeGenerator.h" #include "BatchedTransitionOptimizer.h" +#include "PrototypeFunction.h" #include "JSFunction.h" #include "Interpreter.h" #include "UString.h" @@ -221,6 +222,7 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* d , m_baseScopeDepth(0) , m_codeType(GlobalCode) , m_nextGlobalIndex(-1) + , m_globalConstantIndex(0) , m_globalData(&scopeChain.globalObject()->globalExec()->globalData()) , m_lastOpcodeID(op_end) , m_emitNodeDepth(0) @@ -260,7 +262,7 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* d m_nextGlobalIndex -= symbolTable->size(); for (size_t i = 0; i < functionStack.size(); ++i) { - FuncDeclNode* funcDecl = functionStack[i].get(); + FuncDeclNode* funcDecl = functionStack[i]; globalObject->removeDirect(funcDecl->m_ident); // Make sure our new function is not shadowed by an old property. emitNewFunction(addGlobalVar(funcDecl->m_ident, false), funcDecl); } @@ -276,7 +278,7 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* d emitLoad(newVars[i], jsUndefined()); } else { for (size_t i = 0; i < functionStack.size(); ++i) { - FuncDeclNode* funcDecl = functionStack[i].get(); + FuncDeclNode* funcDecl = functionStack[i]; globalObject->putWithAttributes(exec, funcDecl->m_ident, funcDecl->makeFunction(exec, scopeChain.node()), DontDelete); } for (size_t i = 0; i < varStack.size(); ++i) { @@ -303,6 +305,7 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug , m_dynamicScopeDepth(0) , m_baseScopeDepth(0) , m_codeType(FunctionCode) + , m_globalConstantIndex(0) , m_globalData(&scopeChain.globalObject()->globalExec()->globalData()) , m_lastOpcodeID(op_end) , m_emitNodeDepth(0) @@ -329,12 +332,19 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug } else emitOpcode(op_enter); - if (usesArguments) - emitOpcode(op_create_arguments); + if (usesArguments) { + emitOpcode(op_init_arguments); + + // 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) + emitOpcode(op_create_arguments); + } const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack(); for (size_t i = 0; i < functionStack.size(); ++i) { - FuncDeclNode* funcDecl = functionStack[i].get(); + FuncDeclNode* funcDecl = functionStack[i]; const Identifier& ident = funcDecl->m_ident; m_functions.add(ident.ustring().rep()); emitNewFunction(addVar(ident, false), funcDecl); @@ -377,6 +387,7 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugge , m_dynamicScopeDepth(0) , m_baseScopeDepth(codeBlock->baseScopeDepth()) , m_codeType(EvalCode) + , m_globalConstantIndex(0) , m_globalData(&scopeChain.globalObject()->globalExec()->globalData()) , m_lastOpcodeID(op_end) , m_emitNodeDepth(0) @@ -424,6 +435,36 @@ RegisterID* BytecodeGenerator::registerFor(const Identifier& ident) if (entry.isNull()) return 0; + if (ident == propertyNames().arguments) + createArgumentsIfNecessary(); + + return ®isterFor(entry.getIndex()); +} + +bool BytecodeGenerator::willResolveToArguments(const Identifier& ident) +{ + if (ident != propertyNames().arguments) + return false; + + if (!shouldOptimizeLocals()) + return false; + + SymbolTableEntry entry = symbolTable().get(ident.ustring().rep()); + if (entry.isNull()) + return false; + + if (m_codeBlock->usesArguments() && m_codeType == FunctionCode) + return true; + + return false; +} + +RegisterID* BytecodeGenerator::uncheckedRegisterForArguments() +{ + ASSERT(willResolveToArguments(propertyNames().arguments)); + + SymbolTableEntry entry = symbolTable().get(propertyNames().arguments.ustring().rep()); + ASSERT(!entry.isNull()); return ®isterFor(entry.getIndex()); } @@ -648,6 +689,21 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* ta instructions().append(target->offsetFrom(instructions().size())); return target; } + } else if (m_lastOpcodeID == op_lesseq) { + int dstIndex; + int src1Index; + int src2Index; + + retrieveLastBinaryOp(dstIndex, src1Index, src2Index); + + if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { + rewindBinaryOp(); + emitOpcode(op_jnlesseq); + instructions().append(src1Index); + instructions().append(src2Index); + instructions().append(target->offsetFrom(instructions().size())); + return target; + } } else if (m_lastOpcodeID == op_not) { int dstIndex; int srcIndex; @@ -695,6 +751,24 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* ta return target; } +PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionCall(RegisterID* cond, Label* target) +{ + emitOpcode(op_jneq_ptr); + instructions().append(cond->index()); + instructions().append(m_scopeChain->globalObject()->d()->callFunction); + instructions().append(target->offsetFrom(instructions().size())); + return target; +} + +PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionApply(RegisterID* cond, Label* target) +{ + emitOpcode(op_jneq_ptr); + instructions().append(cond->index()); + instructions().append(m_scopeChain->globalObject()->d()->applyFunction); + instructions().append(target->offsetFrom(instructions().size())); + return target; +} + unsigned BytecodeGenerator::addConstant(FuncDeclNode* n) { // No need to explicitly unique function body nodes -- they're unique already. @@ -717,26 +791,36 @@ unsigned BytecodeGenerator::addConstant(const Identifier& ident) return result.first->second; } -RegisterID* BytecodeGenerator::addConstant(JSValuePtr v) +RegisterID* BytecodeGenerator::addConstant(JSValue v) { - pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(JSValuePtr::encode(v), m_nextConstantIndex); + pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(JSValue::encode(v), m_nextConstantIndex); if (result.second) { RegisterID& constant = m_calleeRegisters[m_nextConstantIndex]; ++m_nextConstantIndex; - m_codeBlock->addConstantRegister(JSValuePtr(v)); + m_codeBlock->addConstantRegister(JSValue(v)); return &constant; } return ®isterFor(result.first->second); } -unsigned BytecodeGenerator::addUnexpectedConstant(JSValuePtr v) +unsigned BytecodeGenerator::addUnexpectedConstant(JSValue v) { return m_codeBlock->addUnexpectedConstant(v); } +RegisterID* BytecodeGenerator::emitLoadGlobalObject(RegisterID* dst, JSObject* globalObject) +{ + if (!m_globalConstantIndex) + m_globalConstantIndex = m_codeBlock->addUnexpectedConstant(globalObject); + emitOpcode(op_unexpected_load); + instructions().append(dst->index()); + instructions().append(m_globalConstantIndex); + return dst; +} + unsigned BytecodeGenerator::addRegExp(RegExp* r) { return m_codeBlock->addRegExp(r); @@ -814,8 +898,8 @@ RegisterID* BytecodeGenerator::emitEqualityOp(OpcodeID opcodeID, RegisterID* dst if (src1->index() == dstIndex && src1->isTemporary() && m_codeBlock->isConstantRegisterIndex(src2->index()) - && m_codeBlock->constantRegister(src2->index() - m_codeBlock->m_numVars).jsValue(m_scopeChain->globalObject()->globalExec()).isString()) { - const UString& value = asString(m_codeBlock->constantRegister(src2->index() - m_codeBlock->m_numVars).jsValue(m_scopeChain->globalObject()->globalExec()))->value(); + && m_codeBlock->constantRegister(src2->index() - m_codeBlock->m_numVars).jsValue().isString()) { + const UString& value = asString(m_codeBlock->constantRegister(src2->index() - m_codeBlock->m_numVars).jsValue())->value(); if (value == "undefined") { rewindUnaryOp(); emitOpcode(op_is_undefined); @@ -879,7 +963,7 @@ RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, double number) // Later we can do the extra work to handle that like the other cases. if (number == HashTraits<double>::emptyValue() || HashTraits<double>::isDeletedValue(number)) return emitLoad(dst, jsNumber(globalData(), number)); - JSValuePtr& valueInMap = m_numberMap.add(number, noValue()).first->second; + JSValue& valueInMap = m_numberMap.add(number, JSValue()).first->second; if (!valueInMap) valueInMap = jsNumber(globalData(), number); return emitLoad(dst, valueInMap); @@ -890,10 +974,10 @@ RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, const Identifier& ident JSString*& stringInMap = m_stringMap.add(identifier.ustring().rep(), 0).first->second; if (!stringInMap) stringInMap = jsOwnedString(globalData(), identifier.ustring()); - return emitLoad(dst, JSValuePtr(stringInMap)); + return emitLoad(dst, JSValue(stringInMap)); } -RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, JSValuePtr v) +RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, JSValue v) { RegisterID* constantID = addConstant(v); if (dst) @@ -1037,7 +1121,7 @@ RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const Identifier& pr return dst; } -RegisterID* BytecodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, int index, JSValuePtr globalObject) +RegisterID* BytecodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, int index, JSValue globalObject) { if (globalObject) { emitOpcode(op_get_global_var); @@ -1054,7 +1138,7 @@ RegisterID* BytecodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, i return dst; } -RegisterID* BytecodeGenerator::emitPutScopedVar(size_t depth, int index, RegisterID* value, JSValuePtr globalObject) +RegisterID* BytecodeGenerator::emitPutScopedVar(size_t depth, int index, RegisterID* value, JSValue globalObject) { if (globalObject) { emitOpcode(op_put_global_var); @@ -1072,18 +1156,65 @@ RegisterID* BytecodeGenerator::emitPutScopedVar(size_t depth, int index, Registe RegisterID* BytecodeGenerator::emitResolveBase(RegisterID* dst, const Identifier& property) { - emitOpcode(op_resolve_base); - instructions().append(dst->index()); - instructions().append(addConstant(property)); - return dst; + size_t depth = 0; + int index = 0; + JSObject* globalObject = 0; + findScopedProperty(property, index, depth, false, globalObject); + if (!globalObject) { + // We can't optimise at all :-( + emitOpcode(op_resolve_base); + instructions().append(dst->index()); + instructions().append(addConstant(property)); + return dst; + } + + // Global object is the base + return emitLoadGlobalObject(dst, globalObject); } RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property) { - emitOpcode(op_resolve_with_base); - instructions().append(baseDst->index()); + size_t depth = 0; + int index = 0; + JSObject* globalObject = 0; + if (!findScopedProperty(property, index, depth, false, globalObject) || !globalObject) { + // We can't optimise at all :-( + emitOpcode(op_resolve_with_base); + instructions().append(baseDst->index()); + instructions().append(propDst->index()); + instructions().append(addConstant(property)); + return baseDst; + } + + bool forceGlobalResolve = false; + if (m_regeneratingForExceptionInfo) { +#if ENABLE(JIT) + forceGlobalResolve = m_codeBlockBeingRegeneratedFrom->hasGlobalResolveInfoAtBytecodeOffset(instructions().size()); +#else + forceGlobalResolve = m_codeBlockBeingRegeneratedFrom->hasGlobalResolveInstructionAtBytecodeOffset(instructions().size()); +#endif + } + + // Global object is the base + emitLoadGlobalObject(baseDst, globalObject); + + if (index != missingSymbolMarker() && !forceGlobalResolve) { + // Directly index the property lookup across multiple scopes. + emitGetScopedVar(propDst, depth, index, globalObject); + return baseDst; + } + +#if ENABLE(JIT) + m_codeBlock->addGlobalResolveInfo(instructions().size()); +#else + m_codeBlock->addGlobalResolveInstruction(instructions().size()); +#endif + emitOpcode(op_resolve_global); instructions().append(propDst->index()); + instructions().append(globalObject); instructions().append(addConstant(property)); + instructions().append(0); + instructions().append(0); return baseDst; } @@ -1096,6 +1227,11 @@ RegisterID* BytecodeGenerator::emitResolveFunction(RegisterID* baseDst, Register return baseDst; } +void BytecodeGenerator::emitMethodCheck() +{ + emitOpcode(op_method_check); +} + RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property) { #if ENABLE(JIT) @@ -1252,8 +1388,15 @@ RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, Regis return emitCall(op_call, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset); } +void BytecodeGenerator::createArgumentsIfNecessary() +{ + if (m_codeBlock->usesArguments() && m_codeType == FunctionCode) + emitOpcode(op_create_arguments); +} + 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); } @@ -1280,7 +1423,7 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi // Generate code for arguments. Vector<RefPtr<RegisterID>, 16> argv; argv.append(thisRegister); - for (ArgumentListNode* n = argumentsNode->m_listNode.get(); n; n = n->m_next.get()) { + 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); @@ -1327,6 +1470,44 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi return dst; } +RegisterID* BytecodeGenerator::emitLoadVarargs(RegisterID* argCountDst, RegisterID* arguments) +{ + ASSERT(argCountDst->index() < arguments->index()); + emitOpcode(op_load_varargs); + instructions().append(argCountDst->index()); + instructions().append(arguments->index()); + return argCountDst; +} + +RegisterID* BytecodeGenerator::emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* argCountRegister, unsigned divot, unsigned startOffset, unsigned endOffset) +{ + ASSERT(func->refCount()); + ASSERT(thisRegister->refCount()); + ASSERT(dst != func); + if (m_shouldEmitProfileHooks) { + emitOpcode(op_profile_will_call); + instructions().append(func->index()); + +#if ENABLE(JIT) + m_codeBlock->addFunctionRegisterInfo(instructions().size(), func->index()); +#endif + } + + emitExpressionInfo(divot, startOffset, endOffset); + + // 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 (m_shouldEmitProfileHooks) { + emitOpcode(op_profile_did_call); + instructions().append(func->index()); + } + return dst; +} + RegisterID* BytecodeGenerator::emitReturn(RegisterID* src) { if (m_codeBlock->needsFullScopeChain()) { @@ -1365,7 +1546,7 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, // Generate code for arguments. Vector<RefPtr<RegisterID>, 16> argv; argv.append(newTemporary()); // reserve space for "this" - for (ArgumentListNode* n = argumentsNode ? argumentsNode->m_listNode.get() : 0; n; n = n->m_next.get()) { + 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); @@ -1416,6 +1597,23 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, return dst; } +RegisterID* BytecodeGenerator::emitStrcat(RegisterID* dst, RegisterID* src, int count) +{ + emitOpcode(op_strcat); + instructions().append(dst->index()); + instructions().append(src->index()); + instructions().append(count); + + return dst; +} + +void BytecodeGenerator::emitToPrimitive(RegisterID* dst, RegisterID* src) +{ + emitOpcode(op_to_primitive); + instructions().append(dst->index()); + instructions().append(src->index()); +} + RegisterID* BytecodeGenerator::emitPushScope(RegisterID* scope) { ASSERT(scope->isTemporary()); @@ -1423,6 +1621,7 @@ RegisterID* BytecodeGenerator::emitPushScope(RegisterID* scope) context.isFinallyBlock = false; m_scopeContextStack.append(context); m_dynamicScopeDepth++; + createArgumentsIfNecessary(); return emitUnaryNoDstOp(op_push_scope, scope); } @@ -1470,8 +1669,17 @@ void BytecodeGenerator::popFinallyContext() LabelScope* BytecodeGenerator::breakTarget(const Identifier& name) { // Reclaim free label scopes. - while (m_labelScopes.size() && !m_labelScopes.last().refCount()) + // + // The condition was previously coded as 'm_labelScopes.size() && !m_labelScopes.last().refCount()', + // however sometimes this appears to lead to GCC going a little haywire and entering the loop with + // size 0, leading to segfaulty badness. We are yet to identify a valid cause within our code to + // cause the GCC codegen to misbehave in this fashion, and as such the following refactoring of the + // loop condition is a workaround. + while (m_labelScopes.size()) { + if (m_labelScopes.last().refCount()) + break; m_labelScopes.removeLast(); + } if (!m_labelScopes.size()) return 0; @@ -1568,14 +1776,10 @@ PassRefPtr<Label> BytecodeGenerator::emitComplexJumpScopes(Label* target, Contro emitLabel(nextInsn.get()); } - // To get here there must be at least one finally block present - do { - ASSERT(topScope->isFinallyBlock); + while (topScope > bottomScope && topScope->isFinallyBlock) { emitJumpSubroutine(topScope->finallyContext.retAddrDst, topScope->finallyContext.finallyAddr); --topScope; - if (!topScope->isFinallyBlock) - break; - } while (topScope > bottomScope); + } } return emitJump(target); } @@ -1622,7 +1826,7 @@ RegisterID* BytecodeGenerator::emitCatch(RegisterID* targetRegister, Label* star return targetRegister; } -RegisterID* BytecodeGenerator::emitNewError(RegisterID* dst, ErrorType type, JSValuePtr message) +RegisterID* BytecodeGenerator::emitNewError(RegisterID* dst, ErrorType type, JSValue message) { emitOpcode(op_new_error); instructions().append(dst->index()); @@ -1652,6 +1856,8 @@ void BytecodeGenerator::emitPushNewScope(RegisterID* dst, Identifier& property, m_scopeContextStack.append(context); m_dynamicScopeDepth++; + createArgumentsIfNecessary(); + emitOpcode(op_push_new_scope); instructions().append(dst->index()); instructions().append(addConstant(property)); @@ -1687,7 +1893,7 @@ static int32_t keyForImmediateSwitch(ExpressionNode* node, int32_t min, int32_t ASSERT(node->isNumber()); double value = static_cast<NumberNode*>(node)->value(); int32_t key = static_cast<int32_t>(value); - ASSERT(JSValuePtr::makeInt32Fast(key) && (JSValuePtr::makeInt32Fast(key).getInt32Fast() == value)); + ASSERT(JSValue::makeInt32Fast(key) && (JSValue::makeInt32Fast(key).getInt32Fast() == value)); ASSERT(key == value); ASSERT(key >= min); ASSERT(key <= max); diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/JavaScriptCore/bytecompiler/BytecodeGenerator.h index a6f245d..6813d69 100644 --- a/JavaScriptCore/bytecompiler/BytecodeGenerator.h +++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.h @@ -81,6 +81,9 @@ namespace JSC { // such register exists. Registers returned by registerFor do not // require explicit reference counting. RegisterID* registerFor(const Identifier&); + + bool willResolveToArguments(const Identifier&); + RegisterID* uncheckedRegisterForArguments(); // Behaves as registerFor does, but ignores dynamic scope as // dynamic scope should not interfere with const initialisation @@ -240,9 +243,10 @@ namespace JSC { RegisterID* emitLoad(RegisterID* dst, bool); RegisterID* emitLoad(RegisterID* dst, double); RegisterID* emitLoad(RegisterID* dst, const Identifier&); - RegisterID* emitLoad(RegisterID* dst, JSValuePtr); + RegisterID* emitLoad(RegisterID* dst, JSValue); RegisterID* emitUnexpectedLoad(RegisterID* dst, bool); RegisterID* emitUnexpectedLoad(RegisterID* dst, double); + RegisterID* emitLoadGlobalObject(RegisterID* dst, JSObject* globalObject); RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src); RegisterID* emitBinaryOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes); @@ -269,13 +273,15 @@ namespace JSC { RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base, OperandTypes()); } RegisterID* emitResolve(RegisterID* dst, const Identifier& property); - RegisterID* emitGetScopedVar(RegisterID* dst, size_t skip, int index, JSValuePtr globalObject); - RegisterID* emitPutScopedVar(size_t skip, int index, RegisterID* value, JSValuePtr globalObject); + RegisterID* emitGetScopedVar(RegisterID* dst, size_t skip, int index, JSValue globalObject); + RegisterID* emitPutScopedVar(size_t skip, int index, RegisterID* value, JSValue globalObject); RegisterID* emitResolveBase(RegisterID* dst, const Identifier& property); RegisterID* emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property); RegisterID* emitResolveFunction(RegisterID* baseDst, RegisterID* funcDst, const Identifier& property); + void emitMethodCheck(); + RegisterID* emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property); RegisterID* emitPutById(RegisterID* base, const Identifier& property, RegisterID* value); RegisterID* emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier&); @@ -288,16 +294,22 @@ namespace JSC { 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* 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* emitStrcat(RegisterID* dst, RegisterID* src, int count); + void emitToPrimitive(RegisterID* dst, RegisterID* src); PassRefPtr<Label> emitLabel(Label*); PassRefPtr<Label> emitJump(Label* target); PassRefPtr<Label> emitJumpIfTrue(RegisterID* cond, Label* target); PassRefPtr<Label> emitJumpIfFalse(RegisterID* cond, Label* target); + PassRefPtr<Label> emitJumpIfNotFunctionCall(RegisterID* cond, Label* target); + PassRefPtr<Label> emitJumpIfNotFunctionApply(RegisterID* cond, Label* target); PassRefPtr<Label> emitJumpScopes(Label* target, int targetScopeDepth); PassRefPtr<Label> emitJumpSubroutine(RegisterID* retAddrDst, Label*); @@ -308,7 +320,7 @@ namespace JSC { RegisterID* emitCatch(RegisterID*, Label* start, Label* end); void emitThrow(RegisterID* exc) { emitUnaryNoDstOp(op_throw, exc); } - RegisterID* emitNewError(RegisterID* dst, ErrorType type, JSValuePtr message); + RegisterID* emitNewError(RegisterID* dst, ErrorType type, JSValue message); void emitPushNewScope(RegisterID* dst, Identifier& property, RegisterID* value); RegisterID* emitPushScope(RegisterID* scope); @@ -345,12 +357,7 @@ namespace JSC { PassRefPtr<Label> emitComplexJumpScopes(Label* target, ControlFlowContext* topScope, ControlFlowContext* bottomScope); - struct JSValueHashTraits : HashTraits<JSValueEncodedAsPointer*> { - static void constructDeletedValue(JSValueEncodedAsPointer*& slot) { slot = JSValuePtr::encode(jsImpossibleValue()); } - static bool isDeletedValue(JSValueEncodedAsPointer* value) { return value == JSValuePtr::encode(jsImpossibleValue()); } - }; - - typedef HashMap<JSValueEncodedAsPointer*, unsigned, PtrHash<JSValueEncodedAsPointer*>, JSValueHashTraits> JSValueMap; + typedef HashMap<EncodedJSValue, unsigned, PtrHash<EncodedJSValue>, JSValueHashTraits> JSValueMap; struct IdentifierMapIndexHashTraits { typedef int TraitType; @@ -362,9 +369,9 @@ namespace JSC { }; typedef HashMap<RefPtr<UString::Rep>, int, IdentifierRepHash, HashTraits<RefPtr<UString::Rep> >, IdentifierMapIndexHashTraits> IdentifierMap; - typedef HashMap<double, JSValuePtr> NumberMap; + 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* newRegister(); @@ -412,8 +419,8 @@ namespace JSC { unsigned addConstant(FuncDeclNode*); unsigned addConstant(FuncExprNode*); unsigned addConstant(const Identifier&); - RegisterID* addConstant(JSValuePtr); - unsigned addUnexpectedConstant(JSValuePtr); + RegisterID* addConstant(JSValue); + unsigned addUnexpectedConstant(JSValue); unsigned addRegExp(RegExp*); Vector<Instruction>& instructions() { return m_codeBlock->instructions(); } @@ -424,6 +431,8 @@ namespace JSC { RegisterID* emitThrowExpressionTooDeepException(); + void createArgumentsIfNecessary(); + bool m_shouldEmitDebugHooks; bool m_shouldEmitProfileHooks; @@ -457,6 +466,7 @@ namespace JSC { int m_nextGlobalIndex; int m_nextParameterIndex; int m_nextConstantIndex; + unsigned m_globalConstantIndex; int m_globalVarStorageOffset; |