summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/bytecompiler
diff options
context:
space:
mode:
authorFeng Qian <fqian@google.com>2009-06-17 12:12:20 -0700
committerFeng Qian <fqian@google.com>2009-06-17 12:12:20 -0700
commit5f1ab04193ad0130ca8204aadaceae083aca9881 (patch)
tree5a92cd389e2cfe7fb67197ce14b38469462379f8 /JavaScriptCore/bytecompiler
parent194315e5a908cc8ed67d597010544803eef1ac59 (diff)
downloadexternal_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.cpp272
-rw-r--r--JavaScriptCore/bytecompiler/BytecodeGenerator.h38
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 &registerFor(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 &registerFor(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 &registerFor(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;