X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/ba379fdc102753d6be2c4d937058fe40257329fe..b80e619319b1def83d1e8b4f84042b661be1be7f:/bytecode/CodeBlock.cpp diff --git a/bytecode/CodeBlock.cpp b/bytecode/CodeBlock.cpp index 1f64992..8cefb1b 100644 --- a/bytecode/CodeBlock.cpp +++ b/bytecode/CodeBlock.cpp @@ -33,6 +33,8 @@ #include "JIT.h" #include "JSValue.h" #include "Interpreter.h" +#include "JSFunction.h" +#include "JSStaticScopeObject.h" #include "Debugger.h" #include "BytecodeGenerator.h" #include @@ -47,9 +49,9 @@ namespace JSC { static UString escapeQuotes(const UString& str) { UString result = str; - int pos = 0; - while ((pos = result.find('\"', pos)) >= 0) { - result = result.substr(0, pos) + "\"\\\"\"" + result.substr(pos + 1); + unsigned pos = 0; + while ((pos = result.find('\"', pos)) != UString::NotFound) { + result = makeString(result.substr(0, pos), "\"\\\"\"", result.substr(pos + 1)); pos += 4; } return result; @@ -60,49 +62,50 @@ static UString valueToSourceString(ExecState* exec, JSValue val) if (!val) return "0"; - if (val.isString()) { - UString result("\""); - result += escapeQuotes(val.toString(exec)) + "\""; - return result; - } + if (val.isString()) + return makeString("\"", escapeQuotes(val.toString(exec)), "\""); return val.toString(exec); } -static CString registerName(int r) +static CString constantName(ExecState* exec, int k, JSValue value) { - if (r == missingThisObjectMarker()) - return ""; - - return (UString("r") + UString::from(r)).UTF8String(); + return makeString(valueToSourceString(exec, value), "(@k", UString::from(k - FirstConstantRegisterIndex), ")").UTF8String(); } -static CString constantName(ExecState* exec, int k, JSValue value) +static CString idName(int id0, const Identifier& ident) { - return (valueToSourceString(exec, value) + "(@k" + UString::from(k) + ")").UTF8String(); + return makeString(ident.ustring(), "(@id", UString::from(id0), ")").UTF8String(); } -static CString idName(int id0, const Identifier& ident) +CString CodeBlock::registerName(ExecState* exec, int r) const { - return (ident.ustring() + "(@id" + UString::from(id0) +")").UTF8String(); + if (r == missingThisObjectMarker()) + return ""; + + if (isConstantRegisterIndex(r)) + return constantName(exec, r, getConstant(r)); + + return makeString("r", UString::from(r)).UTF8String(); } static UString regexpToSourceString(RegExp* regExp) { - UString pattern = UString("/") + regExp->pattern() + "/"; + char postfix[5] = { '/', 0, 0, 0, 0 }; + int index = 1; if (regExp->global()) - pattern += "g"; + postfix[index++] = 'g'; if (regExp->ignoreCase()) - pattern += "i"; + postfix[index++] = 'i'; if (regExp->multiline()) - pattern += "m"; + postfix[index] = 'm'; - return pattern; + return makeString("/", regExp->pattern(), postfix); } static CString regexpName(int re, RegExp* regexp) { - return (regexpToSourceString(regexp) + "(@re" + UString::from(re) + ")").UTF8String(); + return makeString(regexpToSourceString(regexp), "(@re", UString::from(re), ")").UTF8String(); } static UString pointerToSourceString(void* p) @@ -133,56 +136,51 @@ NEVER_INLINE static const char* debugHookName(int debugHookID) return ""; } -static int locationForOffset(const Vector::const_iterator& begin, Vector::const_iterator& it, int offset) -{ - return it - begin + offset; -} - -static void printUnaryOp(int location, Vector::const_iterator& it, const char* op) +void CodeBlock::printUnaryOp(ExecState* exec, int location, Vector::const_iterator& it, const char* op) const { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; - printf("[%4d] %s\t\t %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str()); + printf("[%4d] %s\t\t %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data()); } -static void printBinaryOp(int location, Vector::const_iterator& it, const char* op) +void CodeBlock::printBinaryOp(ExecState* exec, int location, Vector::const_iterator& it, const char* op) const { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; - printf("[%4d] %s\t\t %s, %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str()); + printf("[%4d] %s\t\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); } -static void printConditionalJump(const Vector::const_iterator& begin, Vector::const_iterator& it, int location, const char* op) +void CodeBlock::printConditionalJump(ExecState* exec, const Vector::const_iterator&, Vector::const_iterator& it, int location, const char* op) const { int r0 = (++it)->u.operand; int offset = (++it)->u.operand; - printf("[%4d] %s\t\t %s, %d(->%d)\n", location, op, registerName(r0).c_str(), offset, locationForOffset(begin, it, offset)); + printf("[%4d] %s\t\t %s, %d(->%d)\n", location, op, registerName(exec, r0).data(), offset, location + offset); } -static void printGetByIdOp(int location, Vector::const_iterator& it, const Vector& m_identifiers, const char* op) +void CodeBlock::printGetByIdOp(ExecState* exec, int location, Vector::const_iterator& it, const char* op) const { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int id0 = (++it)->u.operand; - printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str()); + printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data()); it += 4; } -static void printPutByIdOp(int location, Vector::const_iterator& it, const Vector& m_identifiers, const char* op) +void CodeBlock::printPutByIdOp(ExecState* exec, int location, Vector::const_iterator& it, const char* op) const { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; int r1 = (++it)->u.operand; - printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str()); + printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data()); it += 4; } #if ENABLE(JIT) static bool isGlobalResolve(OpcodeID opcodeID) { - return opcodeID == op_resolve_global; + return opcodeID == op_resolve_global || opcodeID == op_resolve_global_dynamic; } static bool isPropertyAccess(OpcodeID opcodeID) @@ -225,49 +223,49 @@ static unsigned instructionOffsetForNth(ExecState* exec, const VectorgetOpcode(op_get_by_id_proto)) { - printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structure).UTF8String().c_str()); + printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(vPC[4].u.structure).UTF8String().data(), pointerToSourceString(vPC[5].u.structure).UTF8String().data()); return; } if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) { - printf(" [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[6].u.structureChain).UTF8String().c_str()); + printf(" [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(vPC[4].u.structure).UTF8String().data(), pointerToSourceString(vPC[5].u.structure).UTF8String().data(), pointerToSourceString(vPC[6].u.structureChain).UTF8String().data()); return; } if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) { - printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structureChain).UTF8String().c_str()); + printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(vPC[4].u.structure).UTF8String().data(), pointerToSourceString(vPC[5].u.structureChain).UTF8String().data()); return; } if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id)) { @@ -319,6 +317,10 @@ void CodeBlock::printStructures(const Instruction* vPC) const printStructure("resolve_global", vPC, 4); return; } + if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global_dynamic)) { + printStructure("resolve_global_dynamic", vPC, 4); + return; + } // These m_instructions doesn't ref Structures. ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_call) || vPC[0].u.opcode == interpreter->getOpcode(op_call_eval) || vPC[0].u.opcode == interpreter->getOpcode(op_construct)); @@ -360,7 +362,7 @@ void CodeBlock::dump(ExecState* exec) const unsigned registerIndex = m_numVars; size_t i = 0; do { - printf(" r%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].jsValue()).ascii()); + printf(" k%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].jsValue()).ascii()); ++i; ++registerIndex; } while (i < m_constantRegisters.size()); @@ -484,7 +486,7 @@ void CodeBlock::dump(ExecState* exec, const Vector::const_iterator& } case op_enter_with_activation: { int r0 = (++it)->u.operand; - printf("[%4d] enter_with_activation %s\n", location, registerName(r0).c_str()); + printf("[%4d] enter_with_activation %s\n", location, registerName(exec, r0).data()); break; } case op_create_arguments: { @@ -497,148 +499,148 @@ void CodeBlock::dump(ExecState* exec, const Vector::const_iterator& } case op_convert_this: { int r0 = (++it)->u.operand; - printf("[%4d] convert_this %s\n", location, registerName(r0).c_str()); + printf("[%4d] convert_this %s\n", location, registerName(exec, r0).data()); break; } case op_new_object: { int r0 = (++it)->u.operand; - printf("[%4d] new_object\t %s\n", location, registerName(r0).c_str()); + printf("[%4d] new_object\t %s\n", location, registerName(exec, r0).data()); break; } case op_new_array: { int dst = (++it)->u.operand; int argv = (++it)->u.operand; int argc = (++it)->u.operand; - printf("[%4d] new_array\t %s, %s, %d\n", location, registerName(dst).c_str(), registerName(argv).c_str(), argc); + printf("[%4d] new_array\t %s, %s, %d\n", location, registerName(exec, dst).data(), registerName(exec, argv).data(), argc); break; } case op_new_regexp: { int r0 = (++it)->u.operand; int re0 = (++it)->u.operand; - printf("[%4d] new_regexp\t %s, %s\n", location, registerName(r0).c_str(), regexpName(re0, regexp(re0)).c_str()); + printf("[%4d] new_regexp\t %s, %s\n", location, registerName(exec, r0).data(), regexpName(re0, regexp(re0)).data()); break; } case op_mov: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; - printf("[%4d] mov\t\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str()); + printf("[%4d] mov\t\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data()); break; } case op_not: { - printUnaryOp(location, it, "not"); + printUnaryOp(exec, location, it, "not"); break; } case op_eq: { - printBinaryOp(location, it, "eq"); + printBinaryOp(exec, location, it, "eq"); break; } case op_eq_null: { - printUnaryOp(location, it, "eq_null"); + printUnaryOp(exec, location, it, "eq_null"); break; } case op_neq: { - printBinaryOp(location, it, "neq"); + printBinaryOp(exec, location, it, "neq"); break; } case op_neq_null: { - printUnaryOp(location, it, "neq_null"); + printUnaryOp(exec, location, it, "neq_null"); break; } case op_stricteq: { - printBinaryOp(location, it, "stricteq"); + printBinaryOp(exec, location, it, "stricteq"); break; } case op_nstricteq: { - printBinaryOp(location, it, "nstricteq"); + printBinaryOp(exec, location, it, "nstricteq"); break; } case op_less: { - printBinaryOp(location, it, "less"); + printBinaryOp(exec, location, it, "less"); break; } case op_lesseq: { - printBinaryOp(location, it, "lesseq"); + printBinaryOp(exec, location, it, "lesseq"); break; } case op_pre_inc: { int r0 = (++it)->u.operand; - printf("[%4d] pre_inc\t\t %s\n", location, registerName(r0).c_str()); + printf("[%4d] pre_inc\t\t %s\n", location, registerName(exec, r0).data()); break; } case op_pre_dec: { int r0 = (++it)->u.operand; - printf("[%4d] pre_dec\t\t %s\n", location, registerName(r0).c_str()); + printf("[%4d] pre_dec\t\t %s\n", location, registerName(exec, r0).data()); break; } case op_post_inc: { - printUnaryOp(location, it, "post_inc"); + printUnaryOp(exec, location, it, "post_inc"); break; } case op_post_dec: { - printUnaryOp(location, it, "post_dec"); + printUnaryOp(exec, location, it, "post_dec"); break; } case op_to_jsnumber: { - printUnaryOp(location, it, "to_jsnumber"); + printUnaryOp(exec, location, it, "to_jsnumber"); break; } case op_negate: { - printUnaryOp(location, it, "negate"); + printUnaryOp(exec, location, it, "negate"); break; } case op_add: { - printBinaryOp(location, it, "add"); + printBinaryOp(exec, location, it, "add"); ++it; break; } case op_mul: { - printBinaryOp(location, it, "mul"); + printBinaryOp(exec, location, it, "mul"); ++it; break; } case op_div: { - printBinaryOp(location, it, "div"); + printBinaryOp(exec, location, it, "div"); ++it; break; } case op_mod: { - printBinaryOp(location, it, "mod"); + printBinaryOp(exec, location, it, "mod"); break; } case op_sub: { - printBinaryOp(location, it, "sub"); + printBinaryOp(exec, location, it, "sub"); ++it; break; } case op_lshift: { - printBinaryOp(location, it, "lshift"); + printBinaryOp(exec, location, it, "lshift"); break; } case op_rshift: { - printBinaryOp(location, it, "rshift"); + printBinaryOp(exec, location, it, "rshift"); break; } case op_urshift: { - printBinaryOp(location, it, "urshift"); + printBinaryOp(exec, location, it, "urshift"); break; } case op_bitand: { - printBinaryOp(location, it, "bitand"); + printBinaryOp(exec, location, it, "bitand"); ++it; break; } case op_bitxor: { - printBinaryOp(location, it, "bitxor"); + printBinaryOp(exec, location, it, "bitxor"); ++it; break; } case op_bitor: { - printBinaryOp(location, it, "bitor"); + printBinaryOp(exec, location, it, "bitor"); ++it; break; } case op_bitnot: { - printUnaryOp(location, it, "bitnot"); + printUnaryOp(exec, location, it, "bitnot"); break; } case op_instanceof: { @@ -646,304 +648,381 @@ void CodeBlock::dump(ExecState* exec, const Vector::const_iterator& int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; int r3 = (++it)->u.operand; - printf("[%4d] instanceof\t\t %s, %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), registerName(r3).c_str()); + printf("[%4d] instanceof\t\t %s, %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data()); break; } case op_typeof: { - printUnaryOp(location, it, "typeof"); + printUnaryOp(exec, location, it, "typeof"); break; } case op_is_undefined: { - printUnaryOp(location, it, "is_undefined"); + printUnaryOp(exec, location, it, "is_undefined"); break; } case op_is_boolean: { - printUnaryOp(location, it, "is_boolean"); + printUnaryOp(exec, location, it, "is_boolean"); break; } case op_is_number: { - printUnaryOp(location, it, "is_number"); + printUnaryOp(exec, location, it, "is_number"); break; } case op_is_string: { - printUnaryOp(location, it, "is_string"); + printUnaryOp(exec, location, it, "is_string"); break; } case op_is_object: { - printUnaryOp(location, it, "is_object"); + printUnaryOp(exec, location, it, "is_object"); break; } case op_is_function: { - printUnaryOp(location, it, "is_function"); + printUnaryOp(exec, location, it, "is_function"); break; } case op_in: { - printBinaryOp(location, it, "in"); + printBinaryOp(exec, location, it, "in"); break; } case op_resolve: { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; - printf("[%4d] resolve\t\t %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str()); + printf("[%4d] resolve\t\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data()); break; } case op_resolve_skip: { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; int skipLevels = (++it)->u.operand; - printf("[%4d] resolve_skip\t %s, %s, %d\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), skipLevels); + printf("[%4d] resolve_skip\t %s, %s, %d\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), skipLevels); break; } case op_resolve_global: { int r0 = (++it)->u.operand; JSValue scope = JSValue((++it)->u.jsCell); int id0 = (++it)->u.operand; - printf("[%4d] resolve_global\t %s, %s, %s\n", location, registerName(r0).c_str(), valueToSourceString(exec, scope).ascii(), idName(id0, m_identifiers[id0]).c_str()); + printf("[%4d] resolve_global\t %s, %s, %s\n", location, registerName(exec, r0).data(), valueToSourceString(exec, scope).ascii(), idName(id0, m_identifiers[id0]).data()); it += 2; break; } + case op_resolve_global_dynamic: { + int r0 = (++it)->u.operand; + JSValue scope = JSValue((++it)->u.jsCell); + int id0 = (++it)->u.operand; + int depth = it[2].u.operand; + printf("[%4d] resolve_global_dynamic\t %s, %s, %s, %d\n", location, registerName(exec, r0).data(), valueToSourceString(exec, scope).ascii(), idName(id0, m_identifiers[id0]).data(), depth); + it += 3; + break; + } case op_get_scoped_var: { int r0 = (++it)->u.operand; int index = (++it)->u.operand; int skipLevels = (++it)->u.operand; - printf("[%4d] get_scoped_var\t %s, %d, %d\n", location, registerName(r0).c_str(), index, skipLevels); + printf("[%4d] get_scoped_var\t %s, %d, %d\n", location, registerName(exec, r0).data(), index, skipLevels); break; } case op_put_scoped_var: { int index = (++it)->u.operand; int skipLevels = (++it)->u.operand; int r0 = (++it)->u.operand; - printf("[%4d] put_scoped_var\t %d, %d, %s\n", location, index, skipLevels, registerName(r0).c_str()); + printf("[%4d] put_scoped_var\t %d, %d, %s\n", location, index, skipLevels, registerName(exec, r0).data()); break; } case op_get_global_var: { int r0 = (++it)->u.operand; JSValue scope = JSValue((++it)->u.jsCell); int index = (++it)->u.operand; - printf("[%4d] get_global_var\t %s, %s, %d\n", location, registerName(r0).c_str(), valueToSourceString(exec, scope).ascii(), index); + printf("[%4d] get_global_var\t %s, %s, %d\n", location, registerName(exec, r0).data(), valueToSourceString(exec, scope).ascii(), index); break; } case op_put_global_var: { JSValue scope = JSValue((++it)->u.jsCell); int index = (++it)->u.operand; int r0 = (++it)->u.operand; - printf("[%4d] put_global_var\t %s, %d, %s\n", location, valueToSourceString(exec, scope).ascii(), index, registerName(r0).c_str()); + printf("[%4d] put_global_var\t %s, %d, %s\n", location, valueToSourceString(exec, scope).ascii(), index, registerName(exec, r0).data()); break; } case op_resolve_base: { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; - printf("[%4d] resolve_base\t %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str()); + printf("[%4d] resolve_base\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data()); break; } case op_resolve_with_base: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int id0 = (++it)->u.operand; - printf("[%4d] resolve_with_base %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str()); + printf("[%4d] resolve_with_base %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data()); break; } case op_get_by_id: { - printGetByIdOp(location, it, m_identifiers, "get_by_id"); + printGetByIdOp(exec, location, it, "get_by_id"); break; } case op_get_by_id_self: { - printGetByIdOp(location, it, m_identifiers, "get_by_id_self"); + printGetByIdOp(exec, location, it, "get_by_id_self"); break; } case op_get_by_id_self_list: { - printGetByIdOp(location, it, m_identifiers, "get_by_id_self_list"); + printGetByIdOp(exec, location, it, "get_by_id_self_list"); break; } case op_get_by_id_proto: { - printGetByIdOp(location, it, m_identifiers, "get_by_id_proto"); + printGetByIdOp(exec, location, it, "get_by_id_proto"); break; } case op_get_by_id_proto_list: { - printGetByIdOp(location, it, m_identifiers, "op_get_by_id_proto_list"); + printGetByIdOp(exec, location, it, "op_get_by_id_proto_list"); break; } case op_get_by_id_chain: { - printGetByIdOp(location, it, m_identifiers, "get_by_id_chain"); + printGetByIdOp(exec, location, it, "get_by_id_chain"); + break; + } + case op_get_by_id_getter_self: { + printGetByIdOp(exec, location, it, "get_by_id_getter_self"); + break; + } + case op_get_by_id_getter_self_list: { + printGetByIdOp(exec, location, it, "get_by_id_getter_self_list"); + break; + } + case op_get_by_id_getter_proto: { + printGetByIdOp(exec, location, it, "get_by_id_getter_proto"); + break; + } + case op_get_by_id_getter_proto_list: { + printGetByIdOp(exec, location, it, "get_by_id_getter_proto_list"); + break; + } + case op_get_by_id_getter_chain: { + printGetByIdOp(exec, location, it, "get_by_id_getter_chain"); + break; + } + case op_get_by_id_custom_self: { + printGetByIdOp(exec, location, it, "get_by_id_custom_self"); + break; + } + case op_get_by_id_custom_self_list: { + printGetByIdOp(exec, location, it, "get_by_id_custom_self_list"); + break; + } + case op_get_by_id_custom_proto: { + printGetByIdOp(exec, location, it, "get_by_id_custom_proto"); + break; + } + case op_get_by_id_custom_proto_list: { + printGetByIdOp(exec, location, it, "get_by_id_custom_proto_list"); + break; + } + case op_get_by_id_custom_chain: { + printGetByIdOp(exec, location, it, "get_by_id_custom_chain"); break; } case op_get_by_id_generic: { - printGetByIdOp(location, it, m_identifiers, "get_by_id_generic"); + printGetByIdOp(exec, location, it, "get_by_id_generic"); break; } case op_get_array_length: { - printGetByIdOp(location, it, m_identifiers, "get_array_length"); + printGetByIdOp(exec, location, it, "get_array_length"); break; } case op_get_string_length: { - printGetByIdOp(location, it, m_identifiers, "get_string_length"); + printGetByIdOp(exec, location, it, "get_string_length"); break; } case op_put_by_id: { - printPutByIdOp(location, it, m_identifiers, "put_by_id"); + printPutByIdOp(exec, location, it, "put_by_id"); break; } case op_put_by_id_replace: { - printPutByIdOp(location, it, m_identifiers, "put_by_id_replace"); + printPutByIdOp(exec, location, it, "put_by_id_replace"); break; } case op_put_by_id_transition: { - printPutByIdOp(location, it, m_identifiers, "put_by_id_transition"); + printPutByIdOp(exec, location, it, "put_by_id_transition"); break; } case op_put_by_id_generic: { - printPutByIdOp(location, it, m_identifiers, "put_by_id_generic"); + printPutByIdOp(exec, location, it, "put_by_id_generic"); break; } case op_put_getter: { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; int r1 = (++it)->u.operand; - printf("[%4d] put_getter\t %s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str()); + printf("[%4d] put_getter\t %s, %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data()); break; } case op_put_setter: { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; int r1 = (++it)->u.operand; - printf("[%4d] put_setter\t %s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str()); + printf("[%4d] put_setter\t %s, %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data()); break; } case op_method_check: { - printf("[%4d] op_method_check\n", location); + printf("[%4d] method_check\n", location); break; } case op_del_by_id: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int id0 = (++it)->u.operand; - printf("[%4d] del_by_id\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str()); + printf("[%4d] del_by_id\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data()); break; } case op_get_by_val: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; - printf("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str()); + printf("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); + break; + } + case op_get_by_pname: { + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + int r2 = (++it)->u.operand; + int r3 = (++it)->u.operand; + int r4 = (++it)->u.operand; + int r5 = (++it)->u.operand; + printf("[%4d] get_by_pname\t %s, %s, %s, %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data(), registerName(exec, r4).data(), registerName(exec, r5).data()); break; } case op_put_by_val: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; - printf("[%4d] put_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str()); + printf("[%4d] put_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); break; } case op_del_by_val: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; - printf("[%4d] del_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str()); + printf("[%4d] del_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); break; } case op_put_by_index: { int r0 = (++it)->u.operand; unsigned n0 = (++it)->u.operand; int r1 = (++it)->u.operand; - printf("[%4d] put_by_index\t %s, %u, %s\n", location, registerName(r0).c_str(), n0, registerName(r1).c_str()); + printf("[%4d] put_by_index\t %s, %u, %s\n", location, registerName(exec, r0).data(), n0, registerName(exec, r1).data()); break; } case op_jmp: { int offset = (++it)->u.operand; - printf("[%4d] jmp\t\t %d(->%d)\n", location, offset, locationForOffset(begin, it, offset)); + printf("[%4d] jmp\t\t %d(->%d)\n", location, offset, location + offset); break; } case op_loop: { int offset = (++it)->u.operand; - printf("[%4d] loop\t\t %d(->%d)\n", location, offset, locationForOffset(begin, it, offset)); + printf("[%4d] loop\t\t %d(->%d)\n", location, offset, location + offset); break; } case op_jtrue: { - printConditionalJump(begin, it, location, "jtrue"); + printConditionalJump(exec, begin, it, location, "jtrue"); break; } case op_loop_if_true: { - printConditionalJump(begin, it, location, "loop_if_true"); + printConditionalJump(exec, begin, it, location, "loop_if_true"); + break; + } + case op_loop_if_false: { + printConditionalJump(exec, begin, it, location, "loop_if_false"); break; } case op_jfalse: { - printConditionalJump(begin, it, location, "jfalse"); + printConditionalJump(exec, begin, it, location, "jfalse"); break; } case op_jeq_null: { - printConditionalJump(begin, it, location, "jeq_null"); + printConditionalJump(exec, begin, it, location, "jeq_null"); break; } case op_jneq_null: { - printConditionalJump(begin, it, location, "jneq_null"); + printConditionalJump(exec, begin, it, location, "jneq_null"); break; } case op_jneq_ptr: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - printf("[%4d] jneq_ptr\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset)); + printf("[%4d] jneq_ptr\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); break; } case op_jnless: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - printf("[%4d] jnless\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset)); + printf("[%4d] jnless\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); break; } case op_jnlesseq: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - printf("[%4d] jnlesseq\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset)); + printf("[%4d] jnlesseq\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); break; } case op_loop_if_less: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - printf("[%4d] loop_if_less\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset)); + printf("[%4d] loop_if_less\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + break; + } + case op_jless: { + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + int offset = (++it)->u.operand; + printf("[%4d] jless\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + break; + } + case op_jlesseq: { + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + int offset = (++it)->u.operand; + printf("[%4d] jlesseq\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); break; } case op_loop_if_lesseq: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - printf("[%4d] loop_if_lesseq\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset)); + printf("[%4d] loop_if_lesseq\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); break; } case op_switch_imm: { int tableIndex = (++it)->u.operand; int defaultTarget = (++it)->u.operand; int scrutineeRegister = (++it)->u.operand; - printf("[%4d] switch_imm\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str()); + printf("[%4d] switch_imm\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data()); break; } case op_switch_char: { int tableIndex = (++it)->u.operand; int defaultTarget = (++it)->u.operand; int scrutineeRegister = (++it)->u.operand; - printf("[%4d] switch_char\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str()); + printf("[%4d] switch_char\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data()); break; } case op_switch_string: { int tableIndex = (++it)->u.operand; int defaultTarget = (++it)->u.operand; int scrutineeRegister = (++it)->u.operand; - printf("[%4d] switch_string\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str()); + printf("[%4d] switch_string\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data()); break; } case op_new_func: { int r0 = (++it)->u.operand; int f0 = (++it)->u.operand; - printf("[%4d] new_func\t\t %s, f%d\n", location, registerName(r0).c_str(), f0); + printf("[%4d] new_func\t\t %s, f%d\n", location, registerName(exec, r0).data(), f0); break; } case op_new_func_exp: { int r0 = (++it)->u.operand; int f0 = (++it)->u.operand; - printf("[%4d] new_func_exp\t %s, f%d\n", location, registerName(r0).c_str(), f0); + printf("[%4d] new_func_exp\t %s, f%d\n", location, registerName(exec, r0).data(), f0); break; } case op_call: { @@ -951,7 +1030,7 @@ void CodeBlock::dump(ExecState* exec, const Vector::const_iterator& int func = (++it)->u.operand; int argCount = (++it)->u.operand; int registerOffset = (++it)->u.operand; - printf("[%4d] call\t\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset); + printf("[%4d] call\t\t %s, %s, %d, %d\n", location, registerName(exec, dst).data(), registerName(exec, func).data(), argCount, registerOffset); break; } case op_call_eval: { @@ -959,7 +1038,7 @@ void CodeBlock::dump(ExecState* exec, const Vector::const_iterator& int func = (++it)->u.operand; int argCount = (++it)->u.operand; int registerOffset = (++it)->u.operand; - printf("[%4d] call_eval\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset); + printf("[%4d] call_eval\t %s, %s, %d, %d\n", location, registerName(exec, dst).data(), registerName(exec, func).data(), argCount, registerOffset); break; } case op_call_varargs: { @@ -967,16 +1046,16 @@ void CodeBlock::dump(ExecState* exec, const Vector::const_iterator& int func = (++it)->u.operand; int argCount = (++it)->u.operand; int registerOffset = (++it)->u.operand; - printf("[%4d] call_varargs\t %s, %s, %s, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), registerName(argCount).c_str(), registerOffset); + printf("[%4d] call_varargs\t %s, %s, %s, %d\n", location, registerName(exec, dst).data(), registerName(exec, func).data(), registerName(exec, argCount).data(), registerOffset); break; } case op_load_varargs: { - printUnaryOp(location, it, "load_varargs"); + printUnaryOp(exec, location, it, "load_varargs"); break; } case op_tear_off_activation: { int r0 = (++it)->u.operand; - printf("[%4d] tear_off_activation\t %s\n", location, registerName(r0).c_str()); + printf("[%4d] tear_off_activation\t %s\n", location, registerName(exec, r0).data()); break; } case op_tear_off_arguments: { @@ -985,7 +1064,7 @@ void CodeBlock::dump(ExecState* exec, const Vector::const_iterator& } case op_ret: { int r0 = (++it)->u.operand; - printf("[%4d] ret\t\t %s\n", location, registerName(r0).c_str()); + printf("[%4d] ret\t\t %s\n", location, registerName(exec, r0).data()); break; } case op_construct: { @@ -995,44 +1074,49 @@ void CodeBlock::dump(ExecState* exec, const Vector::const_iterator& int registerOffset = (++it)->u.operand; int proto = (++it)->u.operand; int thisRegister = (++it)->u.operand; - printf("[%4d] construct\t %s, %s, %d, %d, %s, %s\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset, registerName(proto).c_str(), registerName(thisRegister).c_str()); + printf("[%4d] construct\t %s, %s, %d, %d, %s, %s\n", location, registerName(exec, dst).data(), registerName(exec, func).data(), argCount, registerOffset, registerName(exec, proto).data(), registerName(exec, thisRegister).data()); break; } case op_construct_verify: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; - printf("[%4d] construct_verify\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str()); + printf("[%4d] construct_verify\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data()); break; } case op_strcat: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int count = (++it)->u.operand; - printf("[%4d] op_strcat\t %s, %s, %d\n", location, registerName(r0).c_str(), registerName(r1).c_str(), count); + printf("[%4d] strcat\t\t %s, %s, %d\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), count); break; } case op_to_primitive: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; - printf("[%4d] op_to_primitive\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str()); + printf("[%4d] to_primitive\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data()); break; } case op_get_pnames: { - int r0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - printf("[%4d] get_pnames\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str()); + int r0 = it[1].u.operand; + int r1 = it[2].u.operand; + int r2 = it[3].u.operand; + int r3 = it[4].u.operand; + int offset = it[5].u.operand; + printf("[%4d] get_pnames\t %s, %s, %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data(), offset, location + offset); + it += OPCODE_LENGTH(op_get_pnames) - 1; break; } case op_next_pname: { - int dest = (++it)->u.operand; - int iter = (++it)->u.operand; - int offset = (++it)->u.operand; - printf("[%4d] next_pname\t %s, %s, %d(->%d)\n", location, registerName(dest).c_str(), registerName(iter).c_str(), offset, locationForOffset(begin, it, offset)); + int dest = it[1].u.operand; + int iter = it[4].u.operand; + int offset = it[5].u.operand; + printf("[%4d] next_pname\t %s, %s, %d(->%d)\n", location, registerName(exec, dest).data(), registerName(exec, iter).data(), offset, location + offset); + it += OPCODE_LENGTH(op_next_pname) - 1; break; } case op_push_scope: { int r0 = (++it)->u.operand; - printf("[%4d] push_scope\t %s\n", location, registerName(r0).c_str()); + printf("[%4d] push_scope\t %s\n", location, registerName(exec, r0).data()); break; } case op_pop_scope: { @@ -1043,41 +1127,41 @@ void CodeBlock::dump(ExecState* exec, const Vector::const_iterator& int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; int r1 = (++it)->u.operand; - printf("[%4d] push_new_scope \t%s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str()); + printf("[%4d] push_new_scope \t%s, %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data()); break; } case op_jmp_scopes: { int scopeDelta = (++it)->u.operand; int offset = (++it)->u.operand; - printf("[%4d] jmp_scopes\t^%d, %d(->%d)\n", location, scopeDelta, offset, locationForOffset(begin, it, offset)); + printf("[%4d] jmp_scopes\t^%d, %d(->%d)\n", location, scopeDelta, offset, location + offset); break; } case op_catch: { int r0 = (++it)->u.operand; - printf("[%4d] catch\t\t %s\n", location, registerName(r0).c_str()); + printf("[%4d] catch\t\t %s\n", location, registerName(exec, r0).data()); break; } case op_throw: { int r0 = (++it)->u.operand; - printf("[%4d] throw\t\t %s\n", location, registerName(r0).c_str()); + printf("[%4d] throw\t\t %s\n", location, registerName(exec, r0).data()); break; } case op_new_error: { int r0 = (++it)->u.operand; int errorType = (++it)->u.operand; int k0 = (++it)->u.operand; - printf("[%4d] new_error\t %s, %d, %s\n", location, registerName(r0).c_str(), errorType, constantName(exec, k0, getConstant(k0)).c_str()); + printf("[%4d] new_error\t %s, %d, %s\n", location, registerName(exec, r0).data(), errorType, constantName(exec, k0, getConstant(k0)).data()); break; } case op_jsr: { int retAddrDst = (++it)->u.operand; int offset = (++it)->u.operand; - printf("[%4d] jsr\t\t %s, %d(->%d)\n", location, registerName(retAddrDst).c_str(), offset, locationForOffset(begin, it, offset)); + printf("[%4d] jsr\t\t %s, %d(->%d)\n", location, registerName(exec, retAddrDst).data(), offset, location + offset); break; } case op_sret: { int retAddrSrc = (++it)->u.operand; - printf("[%4d] sret\t\t %s\n", location, registerName(retAddrSrc).c_str()); + printf("[%4d] sret\t\t %s\n", location, registerName(exec, retAddrSrc).data()); break; } case op_debug: { @@ -1089,17 +1173,17 @@ void CodeBlock::dump(ExecState* exec, const Vector::const_iterator& } case op_profile_will_call: { int function = (++it)->u.operand; - printf("[%4d] profile_will_call %s\n", location, registerName(function).c_str()); + printf("[%4d] profile_will_call %s\n", location, registerName(exec, function).data()); break; } case op_profile_did_call: { int function = (++it)->u.operand; - printf("[%4d] profile_did_call\t %s\n", location, registerName(function).c_str()); + printf("[%4d] profile_did_call\t %s\n", location, registerName(exec, function).data()); break; } case op_end: { int r0 = (++it)->u.operand; - printf("[%4d] end\t\t %s\n", location, registerName(r0).c_str()); + printf("[%4d] end\t\t %s\n", location, registerName(exec, r0).data()); break; } } @@ -1246,43 +1330,23 @@ void CodeBlock::dumpStatistics() #endif } -CodeBlock::CodeBlock(ScopeNode* ownerNode) +CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, PassRefPtr sourceProvider, unsigned sourceOffset, SymbolTable* symTab) : m_numCalleeRegisters(0) , m_numVars(0) , m_numParameters(0) - , m_ownerNode(ownerNode) + , m_ownerExecutable(ownerExecutable) , m_globalData(0) #ifndef NDEBUG , m_instructionCount(0) #endif - , m_needsFullScopeChain(false) - , m_usesEval(false) - , m_isNumericCompareFunction(false) - , m_codeType(NativeCode) - , m_source(0) - , m_sourceOffset(0) - , m_exceptionInfo(0) -{ -#if DUMP_CODE_BLOCK_STATISTICS - liveCodeBlockSet.add(this); -#endif -} - -CodeBlock::CodeBlock(ScopeNode* ownerNode, CodeType codeType, PassRefPtr sourceProvider, unsigned sourceOffset) - : m_numCalleeRegisters(0) - , m_numVars(0) - , m_numParameters(0) - , m_ownerNode(ownerNode) - , m_globalData(0) -#ifndef NDEBUG - , m_instructionCount(0) -#endif - , m_needsFullScopeChain(ownerNode->needsActivation()) - , m_usesEval(ownerNode->usesEval()) + , m_needsFullScopeChain(ownerExecutable->needsActivation()) + , m_usesEval(ownerExecutable->usesEval()) + , m_usesArguments(false) , m_isNumericCompareFunction(false) , m_codeType(codeType) , m_source(sourceProvider) , m_sourceOffset(sourceOffset) + , m_symbolTable(symTab) , m_exceptionInfo(new ExceptionInfo) { ASSERT(m_source); @@ -1294,13 +1358,14 @@ CodeBlock::CodeBlock(ScopeNode* ownerNode, CodeType codeType, PassRefPtrderef(); @@ -1319,7 +1384,7 @@ CodeBlock::~CodeBlock() if (Structure* structure = m_methodCallLinkInfos[i].cachedStructure) { structure->deref(); // Both members must be filled at the same time - ASSERT(m_methodCallLinkInfos[i].cachedPrototypeStructure); + ASSERT(!!m_methodCallLinkInfos[i].cachedPrototypeStructure); m_methodCallLinkInfos[i].cachedPrototypeStructure->deref(); } } @@ -1328,7 +1393,7 @@ CodeBlock::~CodeBlock() unlinkCallers(); #endif -#endif // !ENABLE(JIT) +#endif // ENABLE(JIT) #if DUMP_CODE_BLOCK_STATISTICS liveCodeBlockSet.remove(this); @@ -1350,19 +1415,18 @@ void CodeBlock::unlinkCallers() void CodeBlock::derefStructures(Instruction* vPC) const { - ASSERT(m_codeType != NativeCode); Interpreter* interpreter = m_globalData->interpreter; - if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) { + if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_self)) { vPC[4].u.structure->deref(); return; } - if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) { + if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_proto)) { vPC[4].u.structure->deref(); vPC[5].u.structure->deref(); return; } - if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) { + if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_chain)) { vPC[4].u.structure->deref(); vPC[5].u.structureChain->deref(); return; @@ -1377,13 +1441,17 @@ void CodeBlock::derefStructures(Instruction* vPC) const vPC[4].u.structure->deref(); return; } - if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global)) { + if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global) || vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global_dynamic)) { if(vPC[4].u.structure) vPC[4].u.structure->deref(); return; } if ((vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto_list)) - || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self_list))) { + || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self_list)) + || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_proto_list)) + || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_self_list)) + || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_proto_list)) + || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_self_list))) { PolymorphicAccessStructureList* polymorphicStructures = vPC[4].u.polymorphicStructures; polymorphicStructures->derefStructures(vPC[5].u.operand); delete polymorphicStructures; @@ -1396,19 +1464,18 @@ void CodeBlock::derefStructures(Instruction* vPC) const void CodeBlock::refStructures(Instruction* vPC) const { - ASSERT(m_codeType != NativeCode); Interpreter* interpreter = m_globalData->interpreter; - if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) { + if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_self)) { vPC[4].u.structure->ref(); return; } - if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) { + if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_proto)) { vPC[4].u.structure->ref(); vPC[5].u.structure->ref(); return; } - if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) { + if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_chain)) { vPC[4].u.structure->ref(); vPC[5].u.structureChain->ref(); return; @@ -1428,26 +1495,18 @@ void CodeBlock::refStructures(Instruction* vPC) const ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic)); } -void CodeBlock::mark() +void CodeBlock::markAggregate(MarkStack& markStack) { for (size_t i = 0; i < m_constantRegisters.size(); ++i) - if (!m_constantRegisters[i].marked()) - m_constantRegisters[i].mark(); - - for (size_t i = 0; i < m_functionExpressions.size(); ++i) - m_functionExpressions[i]->body()->mark(); - - if (m_rareData) { - for (size_t i = 0; i < m_rareData->m_functions.size(); ++i) - m_rareData->m_functions[i]->body()->mark(); - - m_rareData->m_evalCodeCache.mark(); - } + markStack.append(m_constantRegisters[i].jsValue()); + for (size_t i = 0; i < m_functionExprs.size(); ++i) + m_functionExprs[i]->markAggregate(markStack); + for (size_t i = 0; i < m_functionDecls.size(); ++i) + m_functionDecls[i]->markAggregate(markStack); } void CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame) { - ASSERT(m_codeType != NativeCode); if (m_exceptionInfo) return; @@ -1464,61 +1523,11 @@ void CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame) scopeChain = scopeChain->next; } - switch (m_codeType) { - case FunctionCode: { - FunctionBodyNode* ownerFunctionBodyNode = static_cast(m_ownerNode); - RefPtr newFunctionBody = m_globalData->parser->reparse(m_globalData, ownerFunctionBodyNode); - ASSERT(newFunctionBody); - newFunctionBody->finishParsing(ownerFunctionBodyNode->copyParameters(), ownerFunctionBodyNode->parameterCount()); - - m_globalData->scopeNodeBeingReparsed = newFunctionBody.get(); - - CodeBlock& newCodeBlock = newFunctionBody->bytecodeForExceptionInfoReparse(scopeChain, this); - ASSERT(newCodeBlock.m_exceptionInfo); - ASSERT(newCodeBlock.m_instructionCount == m_instructionCount); - -#if ENABLE(JIT) - JIT::compile(m_globalData, &newCodeBlock); - ASSERT(newFunctionBody->generatedJITCode().size() == ownerNode()->generatedJITCode().size()); -#endif - - m_exceptionInfo.set(newCodeBlock.m_exceptionInfo.release()); - - m_globalData->scopeNodeBeingReparsed = 0; - - break; - } - case EvalCode: { - EvalNode* ownerEvalNode = static_cast(m_ownerNode); - RefPtr newEvalBody = m_globalData->parser->reparse(m_globalData, ownerEvalNode); - - m_globalData->scopeNodeBeingReparsed = newEvalBody.get(); - - EvalCodeBlock& newCodeBlock = newEvalBody->bytecodeForExceptionInfoReparse(scopeChain, this); - ASSERT(newCodeBlock.m_exceptionInfo); - ASSERT(newCodeBlock.m_instructionCount == m_instructionCount); - -#if ENABLE(JIT) - JIT::compile(m_globalData, &newCodeBlock); - ASSERT(newEvalBody->generatedJITCode().size() == ownerNode()->generatedJITCode().size()); -#endif - - m_exceptionInfo.set(newCodeBlock.m_exceptionInfo.release()); - - m_globalData->scopeNodeBeingReparsed = 0; - - break; - } - default: - // CodeBlocks for Global code blocks are transient and therefore to not gain from - // from throwing out there exception information. - ASSERT_NOT_REACHED(); - } + m_exceptionInfo.set(m_ownerExecutable->reparseExceptionInfo(m_globalData, scopeChain, this)); } HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset) { - ASSERT(m_codeType != NativeCode); ASSERT(bytecodeOffset < m_instructionCount); if (!m_rareData) @@ -1537,14 +1546,13 @@ HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset) int CodeBlock::lineNumberForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset) { - ASSERT(m_codeType != NativeCode); ASSERT(bytecodeOffset < m_instructionCount); reparseForExceptionInfoIfNecessary(callFrame); ASSERT(m_exceptionInfo); if (!m_exceptionInfo->m_lineInfo.size()) - return m_ownerNode->source().firstLine(); // Empty function + return m_ownerExecutable->source().firstLine(); // Empty function int low = 0; int high = m_exceptionInfo->m_lineInfo.size(); @@ -1557,13 +1565,12 @@ int CodeBlock::lineNumberForBytecodeOffset(CallFrame* callFrame, unsigned byteco } if (!low) - return m_ownerNode->source().firstLine(); + return m_ownerExecutable->source().firstLine(); return m_exceptionInfo->m_lineInfo[low - 1].lineNumber; } int CodeBlock::expressionRangeForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset) { - ASSERT(m_codeType != NativeCode); ASSERT(bytecodeOffset < m_instructionCount); reparseForExceptionInfoIfNecessary(callFrame); @@ -1603,7 +1610,6 @@ int CodeBlock::expressionRangeForBytecodeOffset(CallFrame* callFrame, unsigned b bool CodeBlock::getByIdExceptionInfoForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, OpcodeID& opcodeID) { - ASSERT(m_codeType != NativeCode); ASSERT(bytecodeOffset < m_instructionCount); reparseForExceptionInfoIfNecessary(callFrame); @@ -1632,7 +1638,6 @@ bool CodeBlock::getByIdExceptionInfoForBytecodeOffset(CallFrame* callFrame, unsi #if ENABLE(JIT) bool CodeBlock::functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex) { - ASSERT(m_codeType != NativeCode); ASSERT(bytecodeOffset < m_instructionCount); if (!m_rareData || !m_rareData->m_functionRegisterInfos.size()) @@ -1656,10 +1661,9 @@ bool CodeBlock::functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& } #endif -#if !ENABLE(JIT) +#if ENABLE(INTERPRETER) bool CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset) { - ASSERT(m_codeType != NativeCode); if (m_globalResolveInstructions.isEmpty()) return false; @@ -1677,10 +1681,10 @@ bool CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOff return false; return true; } -#else +#endif +#if ENABLE(JIT) bool CodeBlock::hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset) { - ASSERT(m_codeType != NativeCode); if (m_globalResolveInfos.isEmpty()) return false; @@ -1700,26 +1704,15 @@ bool CodeBlock::hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset) } #endif -#if ENABLE(JIT) -void CodeBlock::setJITCode(JITCode jitCode) -{ - ASSERT(m_codeType != NativeCode); - ownerNode()->setJITCode(jitCode); -#if !ENABLE(OPCODE_SAMPLING) - if (!BytecodeGenerator::dumpsGeneratedCode()) - m_instructions.clear(); -#endif -} -#endif - void CodeBlock::shrinkToFit() { m_instructions.shrinkToFit(); -#if !ENABLE(JIT) +#if ENABLE(INTERPRETER) m_propertyAccessInstructions.shrinkToFit(); m_globalResolveInstructions.shrinkToFit(); -#else +#endif +#if ENABLE(JIT) m_structureStubInfos.shrinkToFit(); m_globalResolveInfos.shrinkToFit(); m_callLinkInfos.shrinkToFit(); @@ -1727,7 +1720,8 @@ void CodeBlock::shrinkToFit() #endif m_identifiers.shrinkToFit(); - m_functionExpressions.shrinkToFit(); + m_functionDecls.shrinkToFit(); + m_functionExprs.shrinkToFit(); m_constantRegisters.shrinkToFit(); if (m_exceptionInfo) { @@ -1738,7 +1732,6 @@ void CodeBlock::shrinkToFit() if (m_rareData) { m_rareData->m_exceptionHandlers.shrinkToFit(); - m_rareData->m_functions.shrinkToFit(); m_rareData->m_regexps.shrinkToFit(); m_rareData->m_immediateSwitchJumpTables.shrinkToFit(); m_rareData->m_characterSwitchJumpTables.shrinkToFit();