diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-07-11 13:45:28 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-07-11 13:45:28 +0200 |
commit | d6a599dbc9d824a462b2b206316e102bf8136446 (patch) | |
tree | ecb257a5e55b2239d74b90fdad62fccd661cf286 /Source/JavaScriptCore/bytecode | |
parent | 3ccc3a85f09a83557b391aae380d3bf5f81a2911 (diff) | |
download | qtwebkit-d6a599dbc9d824a462b2b206316e102bf8136446.tar.gz |
Imported WebKit commit 8ff1f22783a32de82fee915abd55bd1b298f2644 (http://svn.webkit.org/repository/webkit/trunk@122325)
New snapshot that should work with the latest Qt build system changes
Diffstat (limited to 'Source/JavaScriptCore/bytecode')
19 files changed, 590 insertions, 234 deletions
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp index e0a4da71d..48d0fe728 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp +++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp @@ -48,6 +48,7 @@ #include "UStringConcatenate.h" #include <stdio.h> #include <wtf/StringExtras.h> +#include <wtf/UnusedParam.h> #if ENABLE(DFG_JIT) #include "DFGOperations.h" @@ -93,6 +94,18 @@ static CString idName(int id0, const Identifier& ident) return makeUString(ident.ustring(), "(@id", UString::number(id0), ")").utf8(); } +void CodeBlock::dumpBytecodeCommentAndNewLine(int location) +{ +#if ENABLE(BYTECODE_COMMENTS) + const char* comment = commentForBytecodeOffset(location); + if (comment) + dataLog("\t\t ; %s", comment); +#else + UNUSED_PARAM(location); +#endif + dataLog("\n"); +} + CString CodeBlock::registerName(ExecState* exec, int r) const { if (r == missingThisObjectMarker()) @@ -156,7 +169,8 @@ void CodeBlock::printUnaryOp(ExecState* exec, int location, Vector<Instruction>: int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; - dataLog("[%4d] %s\t\t %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data()); + dataLog("[%4d] %s\t\t %s, %s", location, op, registerName(exec, r0).data(), registerName(exec, r1).data()); + dumpBytecodeCommentAndNewLine(location); } void CodeBlock::printBinaryOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) @@ -164,14 +178,16 @@ void CodeBlock::printBinaryOp(ExecState* exec, int location, Vector<Instruction> int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; - dataLog("[%4d] %s\t\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); + dataLog("[%4d] %s\t\t %s, %s, %s", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); + dumpBytecodeCommentAndNewLine(location); } void CodeBlock::printConditionalJump(ExecState* exec, const Vector<Instruction>::const_iterator&, Vector<Instruction>::const_iterator& it, int location, const char* op) { int r0 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] %s\t\t %s, %d(->%d)\n", location, op, registerName(exec, r0).data(), offset, location + offset); + dataLog("[%4d] %s\t\t %s, %d(->%d)", location, op, registerName(exec, r0).data(), offset, location + offset); + dumpBytecodeCommentAndNewLine(location); } void CodeBlock::printGetByIdOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it) @@ -181,6 +197,9 @@ void CodeBlock::printGetByIdOp(ExecState* exec, int location, Vector<Instruction case op_get_by_id: op = "get_by_id"; break; + case op_get_by_id_out_of_line: + op = "get_by_id_out_of_line"; + break; case op_get_by_id_self: op = "get_by_id_self"; break; @@ -402,7 +421,7 @@ void CodeBlock::printCallOp(ExecState* exec, int location, Vector<Instruction>:: } #endif } - dataLog("\n"); + dumpBytecodeCommentAndNewLine(location); it += 2; } @@ -411,7 +430,8 @@ void CodeBlock::printPutByIdOp(ExecState* exec, int location, Vector<Instruction int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; int r1 = (++it)->u.operand; - dataLog("[%4d] %s\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data()); + dataLog("[%4d] %s\t %s, %s, %s", location, op, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data()); + dumpBytecodeCommentAndNewLine(location); it += 5; } @@ -650,52 +670,61 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int location = it - begin; switch (exec->interpreter()->getOpcodeID(it->u.opcode)) { case op_enter: { - dataLog("[%4d] enter\n", location); + dataLog("[%4d] enter", location); + dumpBytecodeCommentAndNewLine(location); break; } case op_create_activation: { int r0 = (++it)->u.operand; - dataLog("[%4d] create_activation %s\n", location, registerName(exec, r0).data()); + dataLog("[%4d] create_activation %s", location, registerName(exec, r0).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_create_arguments: { int r0 = (++it)->u.operand; - dataLog("[%4d] create_arguments\t %s\n", location, registerName(exec, r0).data()); + dataLog("[%4d] create_arguments\t %s", location, registerName(exec, r0).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_init_lazy_reg: { int r0 = (++it)->u.operand; - dataLog("[%4d] init_lazy_reg\t %s\n", location, registerName(exec, r0).data()); + dataLog("[%4d] init_lazy_reg\t %s", location, registerName(exec, r0).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_create_this: { int r0 = (++it)->u.operand; - dataLog("[%4d] create_this %s\n", location, registerName(exec, r0).data()); + dataLog("[%4d] create_this %s", location, registerName(exec, r0).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_convert_this: { int r0 = (++it)->u.operand; - dataLog("[%4d] convert_this\t %s\n", location, registerName(exec, r0).data()); + dataLog("[%4d] convert_this\t %s", location, registerName(exec, r0).data()); + dumpBytecodeCommentAndNewLine(location); ++it; // Skip value profile. break; } case op_new_object: { int r0 = (++it)->u.operand; - dataLog("[%4d] new_object\t %s\n", location, registerName(exec, r0).data()); + dataLog("[%4d] new_object\t %s", location, registerName(exec, r0).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_new_array: { int dst = (++it)->u.operand; int argv = (++it)->u.operand; int argc = (++it)->u.operand; - dataLog("[%4d] new_array\t %s, %s, %d\n", location, registerName(exec, dst).data(), registerName(exec, argv).data(), argc); + dataLog("[%4d] new_array\t %s, %s, %d", location, registerName(exec, dst).data(), registerName(exec, argv).data(), argc); + dumpBytecodeCommentAndNewLine(location); break; } case op_new_array_buffer: { int dst = (++it)->u.operand; int argv = (++it)->u.operand; int argc = (++it)->u.operand; - dataLog("[%4d] new_array_buffer %s, %d, %d\n", location, registerName(exec, dst).data(), argv, argc); + dataLog("[%4d] new_array_buffer %s, %d, %d", location, registerName(exec, dst).data(), argv, argc); + dumpBytecodeCommentAndNewLine(location); break; } case op_new_regexp: { @@ -703,15 +732,17 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int re0 = (++it)->u.operand; dataLog("[%4d] new_regexp\t %s, ", location, registerName(exec, r0).data()); if (r0 >=0 && r0 < (int)numberOfRegExps()) - dataLog("%s\n", regexpName(re0, regexp(re0)).data()); + dataLog("%s", regexpName(re0, regexp(re0)).data()); else - dataLog("bad_regexp(%d)\n", re0); + dataLog("bad_regexp(%d)", re0); + dumpBytecodeCommentAndNewLine(location); break; } case op_mov: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; - dataLog("[%4d] mov\t\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data()); + dataLog("[%4d] mov\t\t %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_not: { @@ -760,12 +791,14 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& } case op_pre_inc: { int r0 = (++it)->u.operand; - dataLog("[%4d] pre_inc\t\t %s\n", location, registerName(exec, r0).data()); + dataLog("[%4d] pre_inc\t\t %s", location, registerName(exec, r0).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_pre_dec: { int r0 = (++it)->u.operand; - dataLog("[%4d] pre_dec\t\t %s\n", location, registerName(exec, r0).data()); + dataLog("[%4d] pre_dec\t\t %s", location, registerName(exec, r0).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_post_inc: { @@ -837,7 +870,8 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& } case op_check_has_instance: { int base = (++it)->u.operand; - dataLog("[%4d] check_has_instance\t\t %s\n", location, registerName(exec, base).data()); + dataLog("[%4d] check_has_instance\t\t %s", location, registerName(exec, base).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_instanceof: { @@ -845,7 +879,8 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; int r3 = (++it)->u.operand; - dataLog("[%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()); + dataLog("[%4d] instanceof\t\t %s, %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_typeof: { @@ -883,7 +918,8 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& case op_resolve: { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; - dataLog("[%4d] resolve\t\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data()); + dataLog("[%4d] resolve\t\t %s, %s", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data()); + dumpBytecodeCommentAndNewLine(location); it++; break; } @@ -891,14 +927,16 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; int skipLevels = (++it)->u.operand; - dataLog("[%4d] resolve_skip\t %s, %s, %d\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), skipLevels); + dataLog("[%4d] resolve_skip\t %s, %s, %d", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), skipLevels); + dumpBytecodeCommentAndNewLine(location); it++; break; } case op_resolve_global: { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; - dataLog("[%4d] resolve_global\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data()); + dataLog("[%4d] resolve_global\t %s, %s", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data()); + dumpBytecodeCommentAndNewLine(location); it += 3; break; } @@ -908,7 +946,8 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& JSValue scope = JSValue((++it)->u.jsCell.get()); ++it; int depth = (++it)->u.operand; - dataLog("[%4d] resolve_global_dynamic\t %s, %s, %s, %d\n", location, registerName(exec, r0).data(), valueToSourceString(exec, scope).utf8().data(), idName(id0, m_identifiers[id0]).data(), depth); + dataLog("[%4d] resolve_global_dynamic\t %s, %s, %s, %d", location, registerName(exec, r0).data(), valueToSourceString(exec, scope).utf8().data(), idName(id0, m_identifiers[id0]).data(), depth); + dumpBytecodeCommentAndNewLine(location); ++it; break; } @@ -916,7 +955,8 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int index = (++it)->u.operand; int skipLevels = (++it)->u.operand; - dataLog("[%4d] get_scoped_var\t %s, %d, %d\n", location, registerName(exec, r0).data(), index, skipLevels); + dataLog("[%4d] get_scoped_var\t %s, %d, %d", location, registerName(exec, r0).data(), index, skipLevels); + dumpBytecodeCommentAndNewLine(location); it++; break; } @@ -924,20 +964,23 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int index = (++it)->u.operand; int skipLevels = (++it)->u.operand; int r0 = (++it)->u.operand; - dataLog("[%4d] put_scoped_var\t %d, %d, %s\n", location, index, skipLevels, registerName(exec, r0).data()); + dataLog("[%4d] put_scoped_var\t %d, %d, %s", location, index, skipLevels, registerName(exec, r0).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_get_global_var: { int r0 = (++it)->u.operand; WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer; - dataLog("[%4d] get_global_var\t %s, g%d(%p)\n", location, registerName(exec, r0).data(), m_globalObject->findRegisterIndex(registerPointer), registerPointer); + dataLog("[%4d] get_global_var\t %s, g%d(%p)", location, registerName(exec, r0).data(), m_globalObject->findRegisterIndex(registerPointer), registerPointer); + dumpBytecodeCommentAndNewLine(location); it++; break; } case op_get_global_var_watchable: { int r0 = (++it)->u.operand; WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer; - dataLog("[%4d] get_global_var_watchable\t %s, g%d(%p)\n", location, registerName(exec, r0).data(), m_globalObject->findRegisterIndex(registerPointer), registerPointer); + dataLog("[%4d] get_global_var_watchable\t %s, g%d(%p)", location, registerName(exec, r0).data(), m_globalObject->findRegisterIndex(registerPointer), registerPointer); + dumpBytecodeCommentAndNewLine(location); it++; it++; break; @@ -945,13 +988,15 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& case op_put_global_var: { WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer; int r0 = (++it)->u.operand; - dataLog("[%4d] put_global_var\t g%d(%p), %s\n", location, m_globalObject->findRegisterIndex(registerPointer), registerPointer, registerName(exec, r0).data()); + dataLog("[%4d] put_global_var\t g%d(%p), %s", location, m_globalObject->findRegisterIndex(registerPointer), registerPointer, registerName(exec, r0).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_put_global_var_check: { WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer; int r0 = (++it)->u.operand; - dataLog("[%4d] put_global_var_check\t g%d(%p), %s\n", location, m_globalObject->findRegisterIndex(registerPointer), registerPointer, registerName(exec, r0).data()); + dataLog("[%4d] put_global_var_check\t g%d(%p), %s", location, m_globalObject->findRegisterIndex(registerPointer), registerPointer, registerName(exec, r0).data()); + dumpBytecodeCommentAndNewLine(location); it++; it++; break; @@ -960,21 +1005,24 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; int isStrict = (++it)->u.operand; - dataLog("[%4d] resolve_base%s\t %s, %s\n", location, isStrict ? "_strict" : "", registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data()); + dataLog("[%4d] resolve_base%s\t %s, %s", location, isStrict ? "_strict" : "", registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data()); + dumpBytecodeCommentAndNewLine(location); it++; break; } case op_ensure_property_exists: { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; - dataLog("[%4d] ensure_property_exists\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data()); + dataLog("[%4d] ensure_property_exists\t %s, %s", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_resolve_with_base: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int id0 = (++it)->u.operand; - dataLog("[%4d] resolve_with_base %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data()); + dataLog("[%4d] resolve_with_base %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data()); + dumpBytecodeCommentAndNewLine(location); it++; break; } @@ -982,11 +1030,13 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int id0 = (++it)->u.operand; - dataLog("[%4d] resolve_with_this %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data()); + dataLog("[%4d] resolve_with_this %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data()); + dumpBytecodeCommentAndNewLine(location); it++; break; } case op_get_by_id: + case op_get_by_id_out_of_line: case op_get_by_id_self: case op_get_by_id_proto: case op_get_by_id_chain: @@ -1001,7 +1051,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& case op_get_string_length: { printGetByIdOp(exec, location, it); printGetByIdCacheStatus(exec, location); - dataLog("\n"); + dumpBytecodeCommentAndNewLine(location); break; } case op_get_arguments_length: { @@ -1013,6 +1063,10 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& printPutByIdOp(exec, location, it, "put_by_id"); break; } + case op_put_by_id_out_of_line: { + printPutByIdOp(exec, location, it, "put_by_id_out_of_line"); + break; + } case op_put_by_id_replace: { printPutByIdOp(exec, location, it, "put_by_id_replace"); break; @@ -1025,10 +1079,18 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& printPutByIdOp(exec, location, it, "put_by_id_transition_direct"); break; } + case op_put_by_id_transition_direct_out_of_line: { + printPutByIdOp(exec, location, it, "put_by_id_transition_direct_out_of_line"); + break; + } case op_put_by_id_transition_normal: { printPutByIdOp(exec, location, it, "put_by_id_transition_normal"); break; } + case op_put_by_id_transition_normal_out_of_line: { + printPutByIdOp(exec, location, it, "put_by_id_transition_normal_out_of_line"); + break; + } case op_put_by_id_generic: { printPutByIdOp(exec, location, it, "put_by_id_generic"); break; @@ -1038,7 +1100,8 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int id0 = (++it)->u.operand; int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; - dataLog("[%4d] put_getter_setter\t %s, %s, %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); + dataLog("[%4d] put_getter_setter\t %s, %s, %s, %s", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_method_check: { @@ -1070,7 +1133,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& dataLog(")"); } #endif - dataLog("\n"); + dumpBytecodeCommentAndNewLine(location); ++it; printGetByIdOp(exec, location, it); printGetByIdCacheStatus(exec, location); @@ -1081,14 +1144,16 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int id0 = (++it)->u.operand; - dataLog("[%4d] del_by_id\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data()); + dataLog("[%4d] del_by_id\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_get_by_val: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; - dataLog("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); + dataLog("[%4d] get_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); + dumpBytecodeCommentAndNewLine(location); it++; break; } @@ -1096,7 +1161,8 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; - dataLog("[%4d] get_argument_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); + dataLog("[%4d] get_argument_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); + dumpBytecodeCommentAndNewLine(location); ++it; break; } @@ -1107,38 +1173,44 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r3 = (++it)->u.operand; int r4 = (++it)->u.operand; int r5 = (++it)->u.operand; - dataLog("[%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()); + dataLog("[%4d] get_by_pname\t %s, %s, %s, %s, %s, %s", 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()); + dumpBytecodeCommentAndNewLine(location); break; } case op_put_by_val: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; - dataLog("[%4d] put_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); + dataLog("[%4d] put_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_del_by_val: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; - dataLog("[%4d] del_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); + dataLog("[%4d] del_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_put_by_index: { int r0 = (++it)->u.operand; unsigned n0 = (++it)->u.operand; int r1 = (++it)->u.operand; - dataLog("[%4d] put_by_index\t %s, %u, %s\n", location, registerName(exec, r0).data(), n0, registerName(exec, r1).data()); + dataLog("[%4d] put_by_index\t %s, %u, %s", location, registerName(exec, r0).data(), n0, registerName(exec, r1).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_jmp: { int offset = (++it)->u.operand; - dataLog("[%4d] jmp\t\t %d(->%d)\n", location, offset, location + offset); + dataLog("[%4d] jmp\t\t %d(->%d)", location, offset, location + offset); + dumpBytecodeCommentAndNewLine(location); break; } case op_loop: { int offset = (++it)->u.operand; - dataLog("[%4d] loop\t\t %d(->%d)\n", location, offset, location + offset); + dataLog("[%4d] loop\t\t %d(->%d)", location, offset, location + offset); + dumpBytecodeCommentAndNewLine(location); break; } case op_jtrue: { @@ -1169,129 +1241,148 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; void* pointer = (++it)->u.pointer; int offset = (++it)->u.operand; - dataLog("[%4d] jneq_ptr\t\t %s, %p, %d(->%d)\n", location, registerName(exec, r0).data(), pointer, offset, location + offset); + dataLog("[%4d] jneq_ptr\t\t %s, %p, %d(->%d)", location, registerName(exec, r0).data(), pointer, offset, location + offset); + dumpBytecodeCommentAndNewLine(location); break; } case op_jless: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] jless\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dataLog("[%4d] jless\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dumpBytecodeCommentAndNewLine(location); break; } case op_jlesseq: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] jlesseq\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dataLog("[%4d] jlesseq\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dumpBytecodeCommentAndNewLine(location); break; } case op_jgreater: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] jgreater\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dataLog("[%4d] jgreater\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dumpBytecodeCommentAndNewLine(location); break; } case op_jgreatereq: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] jgreatereq\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dataLog("[%4d] jgreatereq\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dumpBytecodeCommentAndNewLine(location); break; } case op_jnless: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] jnless\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dataLog("[%4d] jnless\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dumpBytecodeCommentAndNewLine(location); break; } case op_jnlesseq: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] jnlesseq\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dataLog("[%4d] jnlesseq\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dumpBytecodeCommentAndNewLine(location); break; } case op_jngreater: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] jngreater\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dataLog("[%4d] jngreater\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dumpBytecodeCommentAndNewLine(location); break; } case op_jngreatereq: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] jngreatereq\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dataLog("[%4d] jngreatereq\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dumpBytecodeCommentAndNewLine(location); break; } case op_loop_if_less: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] loop_if_less\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dataLog("[%4d] loop_if_less\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dumpBytecodeCommentAndNewLine(location); break; } case op_loop_if_lesseq: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] loop_if_lesseq\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dataLog("[%4d] loop_if_lesseq\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dumpBytecodeCommentAndNewLine(location); break; } case op_loop_if_greater: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] loop_if_greater\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dataLog("[%4d] loop_if_greater\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dumpBytecodeCommentAndNewLine(location); break; } case op_loop_if_greatereq: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] loop_if_greatereq\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dataLog("[%4d] loop_if_greatereq\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); + dumpBytecodeCommentAndNewLine(location); break; } case op_loop_hint: { - dataLog("[%4d] loop_hint\n", location); + dataLog("[%4d] loop_hint", location); + dumpBytecodeCommentAndNewLine(location); break; } case op_switch_imm: { int tableIndex = (++it)->u.operand; int defaultTarget = (++it)->u.operand; int scrutineeRegister = (++it)->u.operand; - dataLog("[%4d] switch_imm\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data()); + dataLog("[%4d] switch_imm\t %d, %d(->%d), %s", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_switch_char: { int tableIndex = (++it)->u.operand; int defaultTarget = (++it)->u.operand; int scrutineeRegister = (++it)->u.operand; - dataLog("[%4d] switch_char\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data()); + dataLog("[%4d] switch_char\t %d, %d(->%d), %s", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_switch_string: { int tableIndex = (++it)->u.operand; int defaultTarget = (++it)->u.operand; int scrutineeRegister = (++it)->u.operand; - dataLog("[%4d] switch_string\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data()); + dataLog("[%4d] switch_string\t %d, %d(->%d), %s", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_new_func: { int r0 = (++it)->u.operand; int f0 = (++it)->u.operand; int shouldCheck = (++it)->u.operand; - dataLog("[%4d] new_func\t\t %s, f%d, %s\n", location, registerName(exec, r0).data(), f0, shouldCheck ? "<Checked>" : "<Unchecked>"); + dataLog("[%4d] new_func\t\t %s, f%d, %s", location, registerName(exec, r0).data(), f0, shouldCheck ? "<Checked>" : "<Unchecked>"); + dumpBytecodeCommentAndNewLine(location); break; } case op_new_func_exp: { int r0 = (++it)->u.operand; int f0 = (++it)->u.operand; - dataLog("[%4d] new_func_exp\t %s, f%d\n", location, registerName(exec, r0).data(), f0); + dataLog("[%4d] new_func_exp\t %s, f%d", location, registerName(exec, r0).data(), f0); + dumpBytecodeCommentAndNewLine(location); break; } case op_call: { @@ -1307,35 +1398,41 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int thisValue = (++it)->u.operand; int arguments = (++it)->u.operand; int firstFreeRegister = (++it)->u.operand; - dataLog("[%4d] call_varargs\t %s, %s, %s, %d\n", location, registerName(exec, callee).data(), registerName(exec, thisValue).data(), registerName(exec, arguments).data(), firstFreeRegister); + dataLog("[%4d] call_varargs\t %s, %s, %s, %d", location, registerName(exec, callee).data(), registerName(exec, thisValue).data(), registerName(exec, arguments).data(), firstFreeRegister); + dumpBytecodeCommentAndNewLine(location); break; } case op_tear_off_activation: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; - dataLog("[%4d] tear_off_activation\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data()); + dataLog("[%4d] tear_off_activation\t %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_tear_off_arguments: { int r0 = (++it)->u.operand; - dataLog("[%4d] tear_off_arguments %s\n", location, registerName(exec, r0).data()); + dataLog("[%4d] tear_off_arguments %s", location, registerName(exec, r0).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_ret: { int r0 = (++it)->u.operand; - dataLog("[%4d] ret\t\t %s\n", location, registerName(exec, r0).data()); + dataLog("[%4d] ret\t\t %s", location, registerName(exec, r0).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_call_put_result: { int r0 = (++it)->u.operand; - dataLog("[%4d] call_put_result\t\t %s\n", location, registerName(exec, r0).data()); + dataLog("[%4d] call_put_result\t\t %s", location, registerName(exec, r0).data()); + dumpBytecodeCommentAndNewLine(location); it++; break; } case op_ret_object_or_this: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; - dataLog("[%4d] constructor_ret\t\t %s %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data()); + dataLog("[%4d] constructor_ret\t\t %s %s", location, registerName(exec, r0).data(), registerName(exec, r1).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_construct: { @@ -1346,13 +1443,15 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int count = (++it)->u.operand; - dataLog("[%4d] strcat\t\t %s, %s, %d\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), count); + dataLog("[%4d] strcat\t\t %s, %s, %d", location, registerName(exec, r0).data(), registerName(exec, r1).data(), count); + dumpBytecodeCommentAndNewLine(location); break; } case op_to_primitive: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; - dataLog("[%4d] to_primitive\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data()); + dataLog("[%4d] to_primitive\t %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_get_pnames: { @@ -1361,7 +1460,8 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r2 = it[3].u.operand; int r3 = it[4].u.operand; int offset = it[5].u.operand; - dataLog("[%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); + dataLog("[%4d] get_pnames\t %s, %s, %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data(), offset, location + offset); + dumpBytecodeCommentAndNewLine(location); it += OPCODE_LENGTH(op_get_pnames) - 1; break; } @@ -1372,67 +1472,79 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int size = it[4].u.operand; int iter = it[5].u.operand; int offset = it[6].u.operand; - dataLog("[%4d] next_pname\t %s, %s, %s, %s, %s, %d(->%d)\n", location, registerName(exec, dest).data(), registerName(exec, base).data(), registerName(exec, i).data(), registerName(exec, size).data(), registerName(exec, iter).data(), offset, location + offset); + dataLog("[%4d] next_pname\t %s, %s, %s, %s, %s, %d(->%d)", location, registerName(exec, dest).data(), registerName(exec, base).data(), registerName(exec, i).data(), registerName(exec, size).data(), registerName(exec, iter).data(), offset, location + offset); + dumpBytecodeCommentAndNewLine(location); it += OPCODE_LENGTH(op_next_pname) - 1; break; } case op_push_scope: { int r0 = (++it)->u.operand; - dataLog("[%4d] push_scope\t %s\n", location, registerName(exec, r0).data()); + dataLog("[%4d] push_scope\t %s", location, registerName(exec, r0).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_pop_scope: { - dataLog("[%4d] pop_scope\n", location); + dataLog("[%4d] pop_scope", location); + dumpBytecodeCommentAndNewLine(location); break; } case op_push_new_scope: { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; int r1 = (++it)->u.operand; - dataLog("[%4d] push_new_scope \t%s, %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data()); + dataLog("[%4d] push_new_scope \t%s, %s, %s", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_jmp_scopes: { int scopeDelta = (++it)->u.operand; int offset = (++it)->u.operand; - dataLog("[%4d] jmp_scopes\t^%d, %d(->%d)\n", location, scopeDelta, offset, location + offset); + dataLog("[%4d] jmp_scopes\t^%d, %d(->%d)", location, scopeDelta, offset, location + offset); + dumpBytecodeCommentAndNewLine(location); break; } case op_catch: { int r0 = (++it)->u.operand; - dataLog("[%4d] catch\t\t %s\n", location, registerName(exec, r0).data()); + dataLog("[%4d] catch\t\t %s", location, registerName(exec, r0).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_throw: { int r0 = (++it)->u.operand; - dataLog("[%4d] throw\t\t %s\n", location, registerName(exec, r0).data()); + dataLog("[%4d] throw\t\t %s", location, registerName(exec, r0).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_throw_reference_error: { int k0 = (++it)->u.operand; - dataLog("[%4d] throw_reference_error\t %s\n", location, constantName(exec, k0, getConstant(k0)).data()); + dataLog("[%4d] throw_reference_error\t %s", location, constantName(exec, k0, getConstant(k0)).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_debug: { int debugHookID = (++it)->u.operand; int firstLine = (++it)->u.operand; int lastLine = (++it)->u.operand; - dataLog("[%4d] debug\t\t %s, %d, %d\n", location, debugHookName(debugHookID), firstLine, lastLine); + dataLog("[%4d] debug\t\t %s, %d, %d", location, debugHookName(debugHookID), firstLine, lastLine); + dumpBytecodeCommentAndNewLine(location); break; } case op_profile_will_call: { int function = (++it)->u.operand; - dataLog("[%4d] profile_will_call %s\n", location, registerName(exec, function).data()); + dataLog("[%4d] profile_will_call %s", location, registerName(exec, function).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_profile_did_call: { int function = (++it)->u.operand; - dataLog("[%4d] profile_did_call\t %s\n", location, registerName(exec, function).data()); + dataLog("[%4d] profile_did_call\t %s", location, registerName(exec, function).data()); + dumpBytecodeCommentAndNewLine(location); break; } case op_end: { int r0 = (++it)->u.operand; - dataLog("[%4d] end\t\t %s\n", location, registerName(exec, r0).data()); + dataLog("[%4d] end\t\t %s", location, registerName(exec, r0).data()); + dumpBytecodeCommentAndNewLine(location); break; } } @@ -1595,12 +1707,13 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other, SymbolTable* symTab) , m_functionDecls(other.m_functionDecls) , m_functionExprs(other.m_functionExprs) , m_symbolTable(symTab) - , m_speculativeSuccessCounter(0) - , m_speculativeFailCounter(0) - , m_forcedOSRExitCounter(0) + , m_osrExitCounter(0) , m_optimizationDelayCounter(0) , m_reoptimizationRetryCounter(0) , m_lineInfo(other.m_lineInfo) +#if ENABLE(BYTECODE_COMMENTS) + , m_bytecodeCommentIterator(0) +#endif #if ENABLE(JIT) , m_canCompileWithDFGState(DFG::CapabilityLevelNotSet) #endif @@ -1649,10 +1762,12 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlo #endif , m_symbolTable(symTab) , m_alternative(alternative) - , m_speculativeSuccessCounter(0) - , m_speculativeFailCounter(0) + , m_osrExitCounter(0) , m_optimizationDelayCounter(0) , m_reoptimizationRetryCounter(0) +#if ENABLE(BYTECODE_COMMENTS) + , m_bytecodeCommentIterator(0) +#endif { ASSERT(m_source); @@ -1930,7 +2045,9 @@ void CodeBlock::finalizeUnconditionally() Instruction* curInstruction = &instructions()[m_propertyAccessInstructions[i]]; switch (interpreter->getOpcodeID(curInstruction[0].u.opcode)) { case op_get_by_id: + case op_get_by_id_out_of_line: case op_put_by_id: + case op_put_by_id_out_of_line: if (!curInstruction[4].u.structure || Heap::isMarked(curInstruction[4].u.structure.get())) break; if (verboseUnlinking) @@ -1940,6 +2057,8 @@ void CodeBlock::finalizeUnconditionally() break; case op_put_by_id_transition_direct: case op_put_by_id_transition_normal: + case op_put_by_id_transition_direct_out_of_line: + case op_put_by_id_transition_normal_out_of_line: if (Heap::isMarked(curInstruction[4].u.structure.get()) && Heap::isMarked(curInstruction[6].u.structure.get()) && Heap::isMarked(curInstruction[7].u.structureChain.get())) @@ -2127,6 +2246,82 @@ void CodeBlock::stronglyVisitWeakReferences(SlotVisitor& visitor) #endif } +#if ENABLE(BYTECODE_COMMENTS) +// Finds the comment string for the specified bytecode offset/PC is available. +const char* CodeBlock::commentForBytecodeOffset(unsigned bytecodeOffset) +{ + ASSERT(bytecodeOffset < instructions().size()); + + Vector<Comment>& comments = m_bytecodeComments; + size_t numberOfComments = comments.size(); + const char* result = 0; + + if (!numberOfComments) + return 0; // No comments to match with. + + // The next match is most likely the next comment in the list. + // Do a quick check to see if that is a match first. + // m_bytecodeCommentIterator should already be pointing to the + // next comment we should check. + + ASSERT(m_bytecodeCommentIterator < comments.size()); + + size_t i = m_bytecodeCommentIterator; + size_t commentPC = comments[i].pc; + if (commentPC == bytecodeOffset) { + // We've got a match. All done! + m_bytecodeCommentIterator = i; + result = comments[i].string; + } else if (commentPC > bytecodeOffset) { + // The current comment is already greater than the requested PC. + // Start searching from the first comment. + i = 0; + } else { + // Otherwise, the current comment's PC is less than the requested PC. + // Hence, we can just start searching from the next comment in the + // list. + i++; + } + + // If the result is still not found, do a linear search in the range + // that we've determined above. + if (!result) { + for (; i < comments.size(); ++i) { + commentPC = comments[i].pc; + if (commentPC == bytecodeOffset) { + result = comments[i].string; + break; + } + if (comments[i].pc > bytecodeOffset) { + // The current comment PC is already past the requested + // bytecodeOffset. Hence, there are no more possible + // matches. Just fail. + break; + } + } + } + + // Update the iterator to point to the next comment. + if (++i >= numberOfComments) { + // At most point to the last comment entry. This ensures that the + // next time we call this function, the quick checks will at least + // have one entry to check and can fail fast if appropriate. + i = numberOfComments - 1; + } + m_bytecodeCommentIterator = i; + return result; +} + +void CodeBlock::dumpBytecodeComments() +{ + Vector<Comment>& comments = m_bytecodeComments; + printf("Comments for codeblock %p: size %lu\n", this, comments.size()); + for (size_t i = 0; i < comments.size(); ++i) + printf(" pc %lu : '%s'\n", comments[i].pc, comments[i].string); + printf("End of comments for codeblock %p\n", this); +} +#endif // ENABLE_BYTECODE_COMMENTS + HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset) { ASSERT(bytecodeOffset < instructions().size()); @@ -2303,6 +2498,8 @@ void CodeBlock::shrinkToFit(ShrinkMode shrinkMode) m_dfgData->speculationRecovery.shrinkToFit(); m_dfgData->weakReferences.shrinkToFit(); m_dfgData->transitions.shrinkToFit(); + m_dfgData->minifiedDFG.prepareAndShrink(); + m_dfgData->variableEventStream.shrinkToFit(); } #endif } @@ -2596,7 +2793,7 @@ bool CodeBlock::shouldOptimizeNow() dumpValueProfiles(); #endif - if (m_optimizationDelayCounter >= Options::maximumOptimizationDelay) + if (m_optimizationDelayCounter >= Options::maximumOptimizationDelay()) return true; unsigned numberOfLiveNonArgumentValueProfiles; @@ -2607,9 +2804,9 @@ bool CodeBlock::shouldOptimizeNow() dataLog("Profile hotness: %lf, %lf\n", (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles(), (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles()); #endif - if ((!numberOfValueProfiles() || (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles() >= Options::desiredProfileLivenessRate) - && (!totalNumberOfValueProfiles() || (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / totalNumberOfValueProfiles() >= Options::desiredProfileFullnessRate) - && static_cast<unsigned>(m_optimizationDelayCounter) + 1 >= Options::minimumOptimizationDelay) + if ((!numberOfValueProfiles() || (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles() >= Options::desiredProfileLivenessRate()) + && (!totalNumberOfValueProfiles() || (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / totalNumberOfValueProfiles() >= Options::desiredProfileFullnessRate()) + && static_cast<unsigned>(m_optimizationDelayCounter) + 1 >= Options::minimumOptimizationDelay()) return true; ASSERT(m_optimizationDelayCounter < std::numeric_limits<uint8_t>::max()); @@ -2670,7 +2867,7 @@ void CodeBlock::dumpValueProfiles() dataLog(" bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter); } } -#endif +#endif // ENABLE(VERBOSE_VALUE_PROFILE) size_t CodeBlock::predictedMachineCodeSize() { diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h index 4e4fee2b7..ed072f832 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.h +++ b/Source/JavaScriptCore/bytecode/CodeBlock.h @@ -35,12 +35,15 @@ #include "CallReturnOffsetToBytecodeOffset.h" #include "CodeOrigin.h" #include "CodeType.h" +#include "Comment.h" #include "CompactJITCodeMap.h" #include "DFGCodeBlocks.h" #include "DFGCommon.h" #include "DFGExitProfile.h" +#include "DFGMinifiedGraph.h" #include "DFGOSREntry.h" #include "DFGOSRExit.h" +#include "DFGVariableEventStream.h" #include "EvalCodeCache.h" #include "ExecutionCounter.h" #include "ExpressionRangeInfo.h" @@ -66,10 +69,35 @@ #include <wtf/RefCountedArray.h> #include <wtf/FastAllocBase.h> #include <wtf/PassOwnPtr.h> +#include <wtf/Platform.h> #include <wtf/RefPtr.h> #include <wtf/SegmentedVector.h> #include <wtf/Vector.h> +// Set ENABLE_BYTECODE_COMMENTS to 1 to enable recording bytecode generator +// comments for the bytecodes that it generates. This will allow +// CodeBlock::dump() to provide some contextual info about the bytecodes. +// +// The way this comment system works is as follows: +// 1. The BytecodeGenerator calls prependComment() with a constant comment +// string in .text. The string must not be a stack or heap allocated +// string. +// 2. When the BytecodeGenerator's emitOpcode() is called, the last +// prepended comment will be recorded with the PC of the opcode being +// emitted. This comment is being recorded in the CodeBlock's +// m_bytecodeComments. +// 3. When CodeBlock::dump() is called, it will pair up the comments with +// their corresponding bytecodes based on the bytecode and comment's +// PC. If a matching pair is found, the comment will be printed after +// the bytecode. If not, no comment is printed. +// +// NOTE: Enabling this will consume additional memory at runtime to store +// the comments. Since these comments are only useful for VM debugging +// (as opposed to app debugging), this feature is to be disabled by default, +// and can be enabled as needed for VM development use only. + +#define ENABLE_BYTECODE_COMMENTS 0 + namespace JSC { class DFGCodeBlocks; @@ -155,6 +183,12 @@ namespace JSC { return index >= m_numVars; } + void dumpBytecodeCommentAndNewLine(int location); +#if ENABLE(BYTECODE_COMMENTS) + const char* commentForBytecodeOffset(unsigned bytecodeOffset); + void dumpBytecodeComments(); +#endif + HandlerInfo* handlerForBytecodeOffset(unsigned bytecodeOffset); int lineNumberForBytecodeOffset(unsigned bytecodeOffset); void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset); @@ -350,6 +384,18 @@ namespace JSC { m_dfgData->transitions.append( WeakReferenceTransition(*globalData(), ownerExecutable(), codeOrigin, from, to)); } + + DFG::MinifiedGraph& minifiedDFG() + { + createDFGDataIfNecessary(); + return m_dfgData->minifiedDFG; + } + + DFG::VariableEventStream& variableEventStream() + { + createDFGDataIfNecessary(); + return m_dfgData->variableEventStream; + } #endif unsigned bytecodeOffset(Instruction* returnAddress) @@ -365,6 +411,10 @@ namespace JSC { RefCountedArray<Instruction>& instructions() { return m_instructions; } const RefCountedArray<Instruction>& instructions() const { return m_instructions; } +#if ENABLE(BYTECODE_COMMENTS) + Vector<Comment>& bytecodeComments() { return m_bytecodeComments; } +#endif + size_t predictedMachineCodeSize(); bool usesOpcode(OpcodeID); @@ -635,7 +685,7 @@ namespace JSC { if (!numberOfRareCaseProfiles()) return false; unsigned value = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter; - return value >= Options::likelyToTakeSlowCaseMinimumCount && static_cast<double>(value) / m_executionEntryCount >= Options::likelyToTakeSlowCaseThreshold; + return value >= Options::likelyToTakeSlowCaseMinimumCount() && static_cast<double>(value) / m_executionEntryCount >= Options::likelyToTakeSlowCaseThreshold(); } bool couldTakeSlowCase(int bytecodeOffset) @@ -643,7 +693,7 @@ namespace JSC { if (!numberOfRareCaseProfiles()) return false; unsigned value = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter; - return value >= Options::couldTakeSlowCaseMinimumCount && static_cast<double>(value) / m_executionEntryCount >= Options::couldTakeSlowCaseThreshold; + return value >= Options::couldTakeSlowCaseMinimumCount() && static_cast<double>(value) / m_executionEntryCount >= Options::couldTakeSlowCaseThreshold(); } RareCaseProfile* addSpecialFastCaseProfile(int bytecodeOffset) @@ -663,7 +713,15 @@ namespace JSC { if (!numberOfRareCaseProfiles()) return false; unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter; - return specialFastCaseCount >= Options::likelyToTakeSlowCaseMinimumCount && static_cast<double>(specialFastCaseCount) / m_executionEntryCount >= Options::likelyToTakeSlowCaseThreshold; + return specialFastCaseCount >= Options::likelyToTakeSlowCaseMinimumCount() && static_cast<double>(specialFastCaseCount) / m_executionEntryCount >= Options::likelyToTakeSlowCaseThreshold(); + } + + bool couldTakeSpecialFastCase(int bytecodeOffset) + { + if (!numberOfRareCaseProfiles()) + return false; + unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter; + return specialFastCaseCount >= Options::couldTakeSlowCaseMinimumCount() && static_cast<double>(specialFastCaseCount) / m_executionEntryCount >= Options::couldTakeSlowCaseThreshold(); } bool likelyToTakeDeepestSlowCase(int bytecodeOffset) @@ -673,7 +731,7 @@ namespace JSC { unsigned slowCaseCount = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter; unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter; unsigned value = slowCaseCount - specialFastCaseCount; - return value >= Options::likelyToTakeSlowCaseMinimumCount && static_cast<double>(value) / m_executionEntryCount >= Options::likelyToTakeSlowCaseThreshold; + return value >= Options::likelyToTakeSlowCaseMinimumCount() && static_cast<double>(value) / m_executionEntryCount >= Options::likelyToTakeSlowCaseThreshold(); } bool likelyToTakeAnySlowCase(int bytecodeOffset) @@ -683,7 +741,7 @@ namespace JSC { unsigned slowCaseCount = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter; unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter; unsigned value = slowCaseCount + specialFastCaseCount; - return value >= Options::likelyToTakeSlowCaseMinimumCount && static_cast<double>(value) / m_executionEntryCount >= Options::likelyToTakeSlowCaseThreshold; + return value >= Options::likelyToTakeSlowCaseMinimumCount() && static_cast<double>(value) / m_executionEntryCount >= Options::likelyToTakeSlowCaseThreshold(); } unsigned executionEntryCount() const { return m_executionEntryCount; } @@ -905,12 +963,12 @@ namespace JSC { void jitAfterWarmUp() { - m_llintExecuteCounter.setNewThreshold(Options::thresholdForJITAfterWarmUp, this); + m_llintExecuteCounter.setNewThreshold(Options::thresholdForJITAfterWarmUp(), this); } void jitSoon() { - m_llintExecuteCounter.setNewThreshold(Options::thresholdForJITSoon, this); + m_llintExecuteCounter.setNewThreshold(Options::thresholdForJITSoon(), this); } const ExecutionCounter& llintExecuteCounter() const @@ -941,25 +999,25 @@ namespace JSC { // to avoid thrashing. unsigned reoptimizationRetryCounter() const { - ASSERT(m_reoptimizationRetryCounter <= Options::reoptimizationRetryCounterMax); + ASSERT(m_reoptimizationRetryCounter <= Options::reoptimizationRetryCounterMax()); return m_reoptimizationRetryCounter; } void countReoptimization() { m_reoptimizationRetryCounter++; - if (m_reoptimizationRetryCounter > Options::reoptimizationRetryCounterMax) - m_reoptimizationRetryCounter = Options::reoptimizationRetryCounterMax; + if (m_reoptimizationRetryCounter > Options::reoptimizationRetryCounterMax()) + m_reoptimizationRetryCounter = Options::reoptimizationRetryCounterMax(); } int32_t counterValueForOptimizeAfterWarmUp() { - return Options::thresholdForOptimizeAfterWarmUp << reoptimizationRetryCounter(); + return Options::thresholdForOptimizeAfterWarmUp() << reoptimizationRetryCounter(); } int32_t counterValueForOptimizeAfterLongWarmUp() { - return Options::thresholdForOptimizeAfterLongWarmUp << reoptimizationRetryCounter(); + return Options::thresholdForOptimizeAfterLongWarmUp() << reoptimizationRetryCounter(); } int32_t* addressOfJITExecuteCounter() @@ -1039,62 +1097,51 @@ namespace JSC { // in the baseline code. void optimizeSoon() { - m_jitExecuteCounter.setNewThreshold(Options::thresholdForOptimizeSoon << reoptimizationRetryCounter(), this); + m_jitExecuteCounter.setNewThreshold(Options::thresholdForOptimizeSoon() << reoptimizationRetryCounter(), this); } - // The speculative JIT tracks its success rate, so that we can - // decide when to reoptimize. It's interesting to note that these - // counters may overflow without any protection. The success - // counter will overflow before the fail one does, becuase the - // fail one is used as a trigger to reoptimize. So the worst case - // is that the success counter overflows and we reoptimize without - // needing to. But this is harmless. If a method really did - // execute 2^32 times then compiling it again probably won't hurt - // anyone. + uint32_t osrExitCounter() const { return m_osrExitCounter; } - void countSpeculationSuccess() - { - m_speculativeSuccessCounter++; + void countOSRExit() { m_osrExitCounter++; } + + uint32_t* addressOfOSRExitCounter() { return &m_osrExitCounter; } + + static ptrdiff_t offsetOfOSRExitCounter() { return OBJECT_OFFSETOF(CodeBlock, m_osrExitCounter); } + +#if ENABLE(JIT) + uint32_t adjustedExitCountThreshold(uint32_t desiredThreshold) + { + ASSERT(getJITType() == JITCode::DFGJIT); + // Compute this the lame way so we don't saturate. This is called infrequently + // enough that this loop won't hurt us. + unsigned result = desiredThreshold; + for (unsigned n = baselineVersion()->reoptimizationRetryCounter(); n--;) { + unsigned newResult = result << 1; + if (newResult < result) + return std::numeric_limits<uint32_t>::max(); + result = newResult; + } + return result; } - void countSpeculationFailure() + uint32_t exitCountThresholdForReoptimization() { - m_speculativeFailCounter++; + return adjustedExitCountThreshold(Options::osrExitCountForReoptimization()); } - uint32_t speculativeSuccessCounter() const { return m_speculativeSuccessCounter; } - uint32_t speculativeFailCounter() const { return m_speculativeFailCounter; } - uint32_t forcedOSRExitCounter() const { return m_forcedOSRExitCounter; } - - uint32_t* addressOfSpeculativeSuccessCounter() { return &m_speculativeSuccessCounter; } - uint32_t* addressOfSpeculativeFailCounter() { return &m_speculativeFailCounter; } - uint32_t* addressOfForcedOSRExitCounter() { return &m_forcedOSRExitCounter; } - - static ptrdiff_t offsetOfSpeculativeSuccessCounter() { return OBJECT_OFFSETOF(CodeBlock, m_speculativeSuccessCounter); } - static ptrdiff_t offsetOfSpeculativeFailCounter() { return OBJECT_OFFSETOF(CodeBlock, m_speculativeFailCounter); } - static ptrdiff_t offsetOfForcedOSRExitCounter() { return OBJECT_OFFSETOF(CodeBlock, m_forcedOSRExitCounter); } - -#if ENABLE(JIT) - // The number of failures that triggers the use of the ratio. - unsigned largeFailCountThreshold() { return Options::largeFailCountThresholdBase << baselineVersion()->reoptimizationRetryCounter(); } - unsigned largeFailCountThresholdForLoop() { return Options::largeFailCountThresholdBaseForLoop << baselineVersion()->reoptimizationRetryCounter(); } + uint32_t exitCountThresholdForReoptimizationFromLoop() + { + return adjustedExitCountThreshold(Options::osrExitCountForReoptimizationFromLoop()); + } bool shouldReoptimizeNow() { - return (Options::desiredSpeculativeSuccessFailRatio * - speculativeFailCounter() >= speculativeSuccessCounter() - && speculativeFailCounter() >= largeFailCountThreshold()) - || forcedOSRExitCounter() >= - Options::forcedOSRExitCountForReoptimization; + return osrExitCounter() >= exitCountThresholdForReoptimization(); } - + bool shouldReoptimizeFromLoopNow() { - return (Options::desiredSpeculativeSuccessFailRatio * - speculativeFailCounter() >= speculativeSuccessCounter() - && speculativeFailCounter() >= largeFailCountThresholdForLoop()) - || forcedOSRExitCounter() >= - Options::forcedOSRExitCountForReoptimization; + return osrExitCounter() >= exitCountThresholdForReoptimizationFromLoop(); } #endif @@ -1255,6 +1302,8 @@ namespace JSC { SegmentedVector<Watchpoint, 1, 0> watchpoints; Vector<WeakReferenceTransition> transitions; Vector<WriteBarrier<JSCell> > weakReferences; + DFG::VariableEventStream variableEventStream; + DFG::MinifiedGraph minifiedDFG; bool mayBeExecuting; bool isJettisoned; bool livenessHasBeenProved; // Initialized and used on every GC. @@ -1295,13 +1344,15 @@ namespace JSC { ExecutionCounter m_jitExecuteCounter; int32_t m_totalJITExecutions; - uint32_t m_speculativeSuccessCounter; - uint32_t m_speculativeFailCounter; - uint32_t m_forcedOSRExitCounter; + uint32_t m_osrExitCounter; uint16_t m_optimizationDelayCounter; uint16_t m_reoptimizationRetryCounter; Vector<LineInfo> m_lineInfo; +#if ENABLE(BYTECODE_COMMENTS) + Vector<Comment> m_bytecodeComments; + size_t m_bytecodeCommentIterator; +#endif struct RareData { WTF_MAKE_FAST_ALLOCATED; diff --git a/Source/JavaScriptCore/bytecode/Comment.h b/Source/JavaScriptCore/bytecode/Comment.h new file mode 100644 index 000000000..c28f3a068 --- /dev/null +++ b/Source/JavaScriptCore/bytecode/Comment.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef Comment_h +#define Comment_h + +namespace JSC { + +struct Comment { + size_t pc; + const char* string; +}; + +} // namespace JSC + +#endif // Comment_h diff --git a/Source/JavaScriptCore/bytecode/DataFormat.h b/Source/JavaScriptCore/bytecode/DataFormat.h index 4f015486a..51c8afbf6 100644 --- a/Source/JavaScriptCore/bytecode/DataFormat.h +++ b/Source/JavaScriptCore/bytecode/DataFormat.h @@ -47,7 +47,14 @@ enum DataFormat { DataFormatJSInteger = DataFormatJS | DataFormatInteger, DataFormatJSDouble = DataFormatJS | DataFormatDouble, DataFormatJSCell = DataFormatJS | DataFormatCell, - DataFormatJSBoolean = DataFormatJS | DataFormatBoolean + DataFormatJSBoolean = DataFormatJS | DataFormatBoolean, + + // Marker deliminating ordinary data formats and OSR-only data formats. + DataFormatOSRMarker = 32, + + // Special data formats used only for OSR. + DataFormatDead = 33, // Implies jsUndefined(). + DataFormatArguments = 34 // Implies that the arguments object must be reified. }; inline const char* dataFormatToString(DataFormat dataFormat) diff --git a/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp b/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp index 1f2e8260a..12a404981 100644 --- a/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp +++ b/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp @@ -144,13 +144,7 @@ bool ExecutionCounter::setThreshold(CodeBlock* codeBlock) return true; } - int32_t maxThreshold; - if (Options::randomizeExecutionCountsBetweenCheckpoints) - maxThreshold = codeBlock->globalObject()->weakRandomInteger() % Options::maximumExecutionCountsBetweenCheckpoints; - else - maxThreshold = Options::maximumExecutionCountsBetweenCheckpoints; - if (threshold > maxThreshold) - threshold = maxThreshold; + threshold = clippedThreshold(codeBlock->globalObject(), threshold); m_counter = static_cast<int32_t>(-threshold); diff --git a/Source/JavaScriptCore/bytecode/ExecutionCounter.h b/Source/JavaScriptCore/bytecode/ExecutionCounter.h index 1c0d23f0f..f40650a31 100644 --- a/Source/JavaScriptCore/bytecode/ExecutionCounter.h +++ b/Source/JavaScriptCore/bytecode/ExecutionCounter.h @@ -26,6 +26,8 @@ #ifndef ExecutionCounter_h #define ExecutionCounter_h +#include "JSGlobalObject.h" +#include "Options.h" #include <wtf/SimpleStats.h> namespace JSC { @@ -42,6 +44,18 @@ public: const char* status() const; static double applyMemoryUsageHeuristics(int32_t value, CodeBlock*); static int32_t applyMemoryUsageHeuristicsAndConvertToInt(int32_t value, CodeBlock*); + template<typename T> + static T clippedThreshold(JSGlobalObject* globalObject, T threshold) + { + int32_t maxThreshold; + if (Options::randomizeExecutionCountsBetweenCheckpoints()) + maxThreshold = globalObject->weakRandomInteger() % Options::maximumExecutionCountsBetweenCheckpoints(); + else + maxThreshold = Options::maximumExecutionCountsBetweenCheckpoints(); + if (threshold > maxThreshold) + threshold = maxThreshold; + return threshold; + } static int32_t formattedTotalCount(float value) { diff --git a/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp b/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp index a62a43f7f..cb3e8e8b6 100644 --- a/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp +++ b/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp @@ -48,9 +48,9 @@ GetByIdStatus GetByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned unsigned attributesIgnored; JSCell* specificValue; - size_t offset = structure->get( + PropertyOffset offset = structure->get( *profiledBlock->globalData(), ident, attributesIgnored, specificValue); - if (offset == notFound) + if (!isValidOffset(offset)) return GetByIdStatus(NoInformation, false); return GetByIdStatus(Simple, false, StructureSet(structure), offset, specificValue); @@ -88,7 +88,7 @@ void GetByIdStatus::computeForChain(GetByIdStatus& result, CodeBlock* profiledBl result.m_offset = currentStructure->get( *profiledBlock->globalData(), ident, attributesIgnored, specificValue); - if (result.m_offset == notFound) + if (!isValidOffset(result.m_offset)) return; result.m_structureSet.add(structure); @@ -156,12 +156,12 @@ GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytec result.m_offset = structure->get( *profiledBlock->globalData(), ident, attributesIgnored, specificValue); - if (result.m_offset != notFound) { + if (isValidOffset(result.m_offset)) { result.m_structureSet.add(structure); result.m_specificValue = JSValue(specificValue); } - if (result.m_offset != notFound) + if (isValidOffset(result.m_offset)) ASSERT(result.m_structureSet.size()); break; } @@ -176,11 +176,11 @@ GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytec unsigned attributesIgnored; JSCell* specificValue; - size_t myOffset = structure->get( + PropertyOffset myOffset = structure->get( *profiledBlock->globalData(), ident, attributesIgnored, specificValue); - if (myOffset == notFound) { - result.m_offset = notFound; + if (!isValidOffset(myOffset)) { + result.m_offset = invalidOffset; break; } @@ -188,7 +188,7 @@ GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytec result.m_offset = myOffset; result.m_specificValue = JSValue(specificValue); } else if (result.m_offset != myOffset) { - result.m_offset = notFound; + result.m_offset = invalidOffset; break; } else if (result.m_specificValue != JSValue(specificValue)) result.m_specificValue = JSValue(); @@ -196,7 +196,7 @@ GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytec result.m_structureSet.add(structure); } - if (result.m_offset != notFound) + if (isValidOffset(result.m_offset)) ASSERT(result.m_structureSet.size()); break; } @@ -223,11 +223,11 @@ GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytec } default: - ASSERT(result.m_offset == notFound); + ASSERT(!isValidOffset(result.m_offset)); break; } - if (result.m_offset == notFound) { + if (!isValidOffset(result.m_offset)) { result.m_state = TakesSlowPath; result.m_structureSet.clear(); result.m_chain.clear(); diff --git a/Source/JavaScriptCore/bytecode/GetByIdStatus.h b/Source/JavaScriptCore/bytecode/GetByIdStatus.h index 42eadfd68..297ec335f 100644 --- a/Source/JavaScriptCore/bytecode/GetByIdStatus.h +++ b/Source/JavaScriptCore/bytecode/GetByIdStatus.h @@ -26,6 +26,7 @@ #ifndef GetByIdStatus_h #define GetByIdStatus_h +#include "PropertyOffset.h" #include "StructureSet.h" #include <wtf/NotFound.h> @@ -46,13 +47,13 @@ public: GetByIdStatus() : m_state(NoInformation) - , m_offset(notFound) + , m_offset(invalidOffset) { } GetByIdStatus( State state, bool wasSeenInJIT, const StructureSet& structureSet = StructureSet(), - size_t offset = notFound, JSValue specificValue = JSValue(), Vector<Structure*> chain = Vector<Structure*>()) + size_t offset = invalidOffset, JSValue specificValue = JSValue(), Vector<Structure*> chain = Vector<Structure*>()) : m_state(state) , m_structureSet(structureSet) , m_chain(chain) @@ -76,7 +77,7 @@ public: const StructureSet& structureSet() const { return m_structureSet; } const Vector<Structure*>& chain() const { return m_chain; } // Returns empty vector if this is a direct access. JSValue specificValue() const { return m_specificValue; } // Returns JSValue() if there is no specific value. - size_t offset() const { return m_offset; } + PropertyOffset offset() const { return m_offset; } bool wasSeenInJIT() const { return m_wasSeenInJIT; } @@ -88,7 +89,7 @@ private: StructureSet m_structureSet; Vector<Structure*> m_chain; JSValue m_specificValue; - size_t m_offset; + PropertyOffset m_offset; bool m_wasSeenInJIT; }; diff --git a/Source/JavaScriptCore/bytecode/Instruction.h b/Source/JavaScriptCore/bytecode/Instruction.h index 6e76512ff..2e94b452c 100644 --- a/Source/JavaScriptCore/bytecode/Instruction.h +++ b/Source/JavaScriptCore/bytecode/Instruction.h @@ -29,6 +29,7 @@ #ifndef Instruction_h #define Instruction_h +#include "JITStubRoutine.h" #include "MacroAssembler.h" #include "Opcode.h" #include "PropertySlot.h" @@ -52,8 +53,6 @@ namespace JSC { struct ValueProfile; #if ENABLE(JIT) - typedef MacroAssemblerCodeRef PolymorphicAccessStructureListStubRoutineType; - // Structure used by op_get_by_id_self_list and op_get_by_id_proto_list instruction to hold data off the main opcode stream. struct PolymorphicAccessStructureList { WTF_MAKE_FAST_ALLOCATED; @@ -61,7 +60,7 @@ namespace JSC { struct PolymorphicStubInfo { bool isChain; bool isDirect; - PolymorphicAccessStructureListStubRoutineType stubRoutine; + RefPtr<JITStubRoutine> stubRoutine; WriteBarrier<Structure> base; union { WriteBarrierBase<Structure> proto; @@ -73,7 +72,7 @@ namespace JSC { u.proto.clear(); } - void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, bool isDirect) + void set(JSGlobalData& globalData, JSCell* owner, PassRefPtr<JITStubRoutine> _stubRoutine, Structure* _base, bool isDirect) { stubRoutine = _stubRoutine; base.set(globalData, owner, _base); @@ -82,7 +81,7 @@ namespace JSC { this->isDirect = isDirect; } - void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, Structure* _proto, bool isDirect) + void set(JSGlobalData& globalData, JSCell* owner, PassRefPtr<JITStubRoutine> _stubRoutine, Structure* _base, Structure* _proto, bool isDirect) { stubRoutine = _stubRoutine; base.set(globalData, owner, _base); @@ -91,7 +90,7 @@ namespace JSC { this->isDirect = isDirect; } - void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, StructureChain* _chain, bool isDirect) + void set(JSGlobalData& globalData, JSCell* owner, PassRefPtr<JITStubRoutine> _stubRoutine, Structure* _base, StructureChain* _chain, bool isDirect) { stubRoutine = _stubRoutine; base.set(globalData, owner, _base); @@ -105,17 +104,17 @@ namespace JSC { { } - PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, bool isDirect) + PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PassRefPtr<JITStubRoutine> stubRoutine, Structure* firstBase, bool isDirect) { list[0].set(globalData, owner, stubRoutine, firstBase, isDirect); } - PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, Structure* firstProto, bool isDirect) + PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PassRefPtr<JITStubRoutine> stubRoutine, Structure* firstBase, Structure* firstProto, bool isDirect) { list[0].set(globalData, owner, stubRoutine, firstBase, firstProto, isDirect); } - PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, StructureChain* firstChain, bool isDirect) + PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PassRefPtr<JITStubRoutine> stubRoutine, Structure* firstBase, StructureChain* firstChain, bool isDirect) { list[0].set(globalData, owner, stubRoutine, firstBase, firstChain, isDirect); } diff --git a/Source/JavaScriptCore/bytecode/Opcode.h b/Source/JavaScriptCore/bytecode/Opcode.h index e0cff165a..14cefb9d9 100644 --- a/Source/JavaScriptCore/bytecode/Opcode.h +++ b/Source/JavaScriptCore/bytecode/Opcode.h @@ -108,6 +108,7 @@ namespace JSC { macro(op_resolve_with_base, 5) /* has value profiling */ \ macro(op_resolve_with_this, 5) /* has value profiling */ \ macro(op_get_by_id, 9) /* has value profiling */ \ + macro(op_get_by_id_out_of_line, 9) /* has value profiling */ \ macro(op_get_by_id_self, 9) /* has value profiling */ \ macro(op_get_by_id_proto, 9) /* has value profiling */ \ macro(op_get_by_id_chain, 9) /* has value profiling */ \ @@ -122,9 +123,12 @@ namespace JSC { macro(op_get_string_length, 9) /* has value profiling */ \ macro(op_get_arguments_length, 4) \ macro(op_put_by_id, 9) \ + macro(op_put_by_id_out_of_line, 9) \ macro(op_put_by_id_transition, 9) \ macro(op_put_by_id_transition_direct, 9) \ + macro(op_put_by_id_transition_direct_out_of_line, 9) \ macro(op_put_by_id_transition_normal, 9) \ + macro(op_put_by_id_transition_normal_out_of_line, 9) \ macro(op_put_by_id_replace, 9) \ macro(op_put_by_id_generic, 9) \ macro(op_del_by_id, 4) \ diff --git a/Source/JavaScriptCore/bytecode/Operands.h b/Source/JavaScriptCore/bytecode/Operands.h index 05a24d0fd..8ea3e5b60 100644 --- a/Source/JavaScriptCore/bytecode/Operands.h +++ b/Source/JavaScriptCore/bytecode/Operands.h @@ -115,6 +115,13 @@ public: const T& operand(int operand) const { return const_cast<const T&>(const_cast<Operands*>(this)->operand(operand)); } + bool hasOperand(int operand) const + { + if (operandIsArgument(operand)) + return true; + return static_cast<size_t>(operand) < numberOfLocals(); + } + void setOperand(int operand, const T& value) { if (operandIsArgument(operand)) { @@ -126,6 +133,39 @@ public: setLocal(operand, value); } + size_t size() const { return numberOfArguments() + numberOfLocals(); } + const T& at(size_t index) const + { + if (index < numberOfArguments()) + return m_arguments[index]; + return m_locals[index - numberOfArguments()]; + } + T& at(size_t index) + { + if (index < numberOfArguments()) + return m_arguments[index]; + return m_locals[index - numberOfArguments()]; + } + const T& operator[](size_t index) const { return at(index); } + T& operator[](size_t index) { return at(index); } + + bool isArgument(size_t index) const { return index < numberOfArguments(); } + bool isVariable(size_t index) const { return !isArgument(index); } + int argumentForIndex(size_t index) const + { + return index; + } + int variableForIndex(size_t index) const + { + return index - m_arguments.size(); + } + int operandForIndex(size_t index) const + { + if (index < numberOfArguments()) + return argumentToOperand(index); + return index - numberOfArguments(); + } + void setOperandFirstTime(int operand, const T& value) { if (operandIsArgument(operand)) { @@ -165,6 +205,16 @@ void dumpOperands(Operands<T, Traits>& operands, FILE* out) } } +template<typename T, typename Traits> +void dumpOperands(const Operands<T, Traits>& operands, FILE* out) +{ + // Use const-cast because: + // 1) I don't feel like writing this code twice, and + // 2) Some dump() methods may not be const, and I don't really care if that's + // the case. + dumpOperands(*const_cast<Operands<T, Traits>*>(&operands), out); +} + } // namespace JSC #endif // Operands_h diff --git a/Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.cpp b/Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.cpp index 170615b73..3a87567d8 100644 --- a/Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.cpp +++ b/Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.cpp @@ -42,7 +42,7 @@ PutByIdAccess PutByIdAccess::fromStructureStubInfo( case access_put_by_id_replace: result.m_type = Replace; result.m_oldStructure.copyFrom(stubInfo.u.putByIdReplace.baseObjectStructure); - result.m_stubRoutine = MacroAssemblerCodeRef::createSelfManagedCodeRef(initialSlowPath); + result.m_stubRoutine = JITStubRoutine::createSelfManagedRoutine(initialSlowPath); break; case access_put_by_id_transition_direct: diff --git a/Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.h b/Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.h index 60b632d52..4a20b6d1c 100644 --- a/Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.h +++ b/Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.h @@ -60,7 +60,7 @@ public: Structure* oldStructure, Structure* newStructure, StructureChain* chain, - MacroAssemblerCodeRef stubRoutine) + PassRefPtr<JITStubRoutine> stubRoutine) { PutByIdAccess result; result.m_type = Transition; @@ -75,7 +75,7 @@ public: JSGlobalData& globalData, JSCell* owner, Structure* structure, - MacroAssemblerCodeRef stubRoutine) + PassRefPtr<JITStubRoutine> stubRoutine) { PutByIdAccess result; result.m_type = Replace; @@ -123,7 +123,7 @@ public: return m_chain.get(); } - MacroAssemblerCodeRef stubRoutine() const + PassRefPtr<JITStubRoutine> stubRoutine() const { ASSERT(isTransition() || isReplace()); return m_stubRoutine; @@ -136,7 +136,7 @@ private: WriteBarrier<Structure> m_oldStructure; WriteBarrier<Structure> m_newStructure; WriteBarrier<StructureChain> m_chain; - MacroAssemblerCodeRef m_stubRoutine; + RefPtr<JITStubRoutine> m_stubRoutine; }; class PolymorphicPutByIdList { @@ -161,7 +161,7 @@ public: MacroAssemblerCodePtr currentSlowPathTarget() const { - return m_list.last().stubRoutine().code(); + return m_list.last().stubRoutine()->code().code(); } void addAccess(const PutByIdAccess&); diff --git a/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp b/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp index 3715606fe..e9456313a 100644 --- a/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp +++ b/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp @@ -43,12 +43,13 @@ PutByIdStatus PutByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned Structure* structure = instruction[4].u.structure.get(); if (!structure) - return PutByIdStatus(NoInformation, 0, 0, 0, notFound); + return PutByIdStatus(NoInformation, 0, 0, 0, invalidOffset); - if (instruction[0].u.opcode == llint_op_put_by_id) { - size_t offset = structure->get(*profiledBlock->globalData(), ident); - if (offset == notFound) - return PutByIdStatus(NoInformation, 0, 0, 0, notFound); + if (instruction[0].u.opcode == llint_op_put_by_id + || instruction[0].u.opcode == llint_op_put_by_id_out_of_line) { + PropertyOffset offset = structure->get(*profiledBlock->globalData(), ident); + if (!isValidOffset(offset)) + return PutByIdStatus(NoInformation, 0, 0, 0, invalidOffset); return PutByIdStatus(SimpleReplace, structure, 0, 0, offset); } @@ -56,20 +57,22 @@ PutByIdStatus PutByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned ASSERT(structure->transitionWatchpointSetHasBeenInvalidated()); ASSERT(instruction[0].u.opcode == llint_op_put_by_id_transition_direct - || instruction[0].u.opcode == llint_op_put_by_id_transition_normal); + || instruction[0].u.opcode == llint_op_put_by_id_transition_normal + || instruction[0].u.opcode == llint_op_put_by_id_transition_direct_out_of_line + || instruction[0].u.opcode == llint_op_put_by_id_transition_normal_out_of_line); Structure* newStructure = instruction[6].u.structure.get(); StructureChain* chain = instruction[7].u.structureChain.get(); ASSERT(newStructure); ASSERT(chain); - size_t offset = newStructure->get(*profiledBlock->globalData(), ident); - if (offset == notFound) - return PutByIdStatus(NoInformation, 0, 0, 0, notFound); + PropertyOffset offset = newStructure->get(*profiledBlock->globalData(), ident); + if (!isValidOffset(offset)) + return PutByIdStatus(NoInformation, 0, 0, 0, invalidOffset); return PutByIdStatus(SimpleTransition, structure, newStructure, chain, offset); #else - return PutByIdStatus(NoInformation, 0, 0, 0, notFound); + return PutByIdStatus(NoInformation, 0, 0, 0, invalidOffset); #endif } @@ -83,7 +86,7 @@ PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytec return computeFromLLInt(profiledBlock, bytecodeIndex, ident); if (profiledBlock->likelyToTakeSlowCase(bytecodeIndex)) - return PutByIdStatus(TakesSlowPath, 0, 0, 0, notFound); + return PutByIdStatus(TakesSlowPath, 0, 0, 0, invalidOffset); StructureStubInfo& stubInfo = profiledBlock->getStubInfo(bytecodeIndex); if (!stubInfo.seen) @@ -94,24 +97,24 @@ PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytec return computeFromLLInt(profiledBlock, bytecodeIndex, ident); case access_put_by_id_replace: { - size_t offset = stubInfo.u.putByIdReplace.baseObjectStructure->get( + PropertyOffset offset = stubInfo.u.putByIdReplace.baseObjectStructure->get( *profiledBlock->globalData(), ident); - if (offset != notFound) { + if (isValidOffset(offset)) { return PutByIdStatus( SimpleReplace, stubInfo.u.putByIdReplace.baseObjectStructure.get(), 0, 0, offset); } - return PutByIdStatus(TakesSlowPath, 0, 0, 0, notFound); + return PutByIdStatus(TakesSlowPath, 0, 0, 0, invalidOffset); } case access_put_by_id_transition_normal: case access_put_by_id_transition_direct: { ASSERT(stubInfo.u.putByIdTransition.previousStructure->transitionWatchpointSetHasBeenInvalidated()); - size_t offset = stubInfo.u.putByIdTransition.structure->get( + PropertyOffset offset = stubInfo.u.putByIdTransition.structure->get( *profiledBlock->globalData(), ident); - if (offset != notFound) { + if (isValidOffset(offset)) { return PutByIdStatus( SimpleTransition, stubInfo.u.putByIdTransition.previousStructure.get(), @@ -119,14 +122,14 @@ PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytec stubInfo.u.putByIdTransition.chain.get(), offset); } - return PutByIdStatus(TakesSlowPath, 0, 0, 0, notFound); + return PutByIdStatus(TakesSlowPath, 0, 0, 0, invalidOffset); } default: - return PutByIdStatus(TakesSlowPath, 0, 0, 0, notFound); + return PutByIdStatus(TakesSlowPath, 0, 0, 0, invalidOffset); } #else // ENABLE(JIT) - return PutByIdStatus(NoInformation, 0, 0, 0, notFound); + return PutByIdStatus(NoInformation, 0, 0, 0, invalidOffset); #endif // ENABLE(JIT) } diff --git a/Source/JavaScriptCore/bytecode/PutByIdStatus.h b/Source/JavaScriptCore/bytecode/PutByIdStatus.h index a6d95a449..694915244 100644 --- a/Source/JavaScriptCore/bytecode/PutByIdStatus.h +++ b/Source/JavaScriptCore/bytecode/PutByIdStatus.h @@ -26,6 +26,7 @@ #ifndef PutByIdStatus_h #define PutByIdStatus_h +#include "PropertyOffset.h" #include <wtf/NotFound.h> namespace JSC { @@ -55,7 +56,7 @@ public: , m_oldStructure(0) , m_newStructure(0) , m_structureChain(0) - , m_offset(notFound) + , m_offset(invalidOffset) { } @@ -64,7 +65,7 @@ public: Structure* oldStructure, Structure* newStructure, StructureChain* structureChain, - size_t offset) + PropertyOffset offset) : m_state(state) , m_oldStructure(oldStructure) , m_newStructure(newStructure) @@ -74,7 +75,7 @@ public: ASSERT((m_state == NoInformation || m_state == TakesSlowPath) == !m_oldStructure); ASSERT((m_state != SimpleTransition) == !m_newStructure); ASSERT((m_state != SimpleTransition) == !m_structureChain); - ASSERT((m_state == NoInformation || m_state == TakesSlowPath) == (m_offset == notFound)); + ASSERT((m_state == NoInformation || m_state == TakesSlowPath) == (m_offset == invalidOffset)); } static PutByIdStatus computeFor(CodeBlock*, unsigned bytecodeIndex, Identifier&); @@ -90,7 +91,7 @@ public: Structure* oldStructure() const { return m_oldStructure; } Structure* newStructure() const { return m_newStructure; } StructureChain* structureChain() const { return m_structureChain; } - size_t offset() const { return m_offset; } + PropertyOffset offset() const { return m_offset; } private: static PutByIdStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex, Identifier&); @@ -99,7 +100,7 @@ private: Structure* m_oldStructure; Structure* m_newStructure; StructureChain* m_structureChain; - size_t m_offset; + PropertyOffset m_offset; }; } // namespace JSC diff --git a/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.cpp b/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.cpp index ff138704c..4afee248d 100644 --- a/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.cpp +++ b/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.cpp @@ -32,17 +32,19 @@ namespace JSC { +#if ENABLE(LLINT) || ENABLE(JIT) static ResolveGlobalStatus computeForStructure(CodeBlock* codeBlock, Structure* structure, Identifier& identifier) { unsigned attributesIgnored; JSCell* specificValue; - size_t offset = structure->get( + PropertyOffset offset = structure->get( *codeBlock->globalData(), identifier, attributesIgnored, specificValue); - if (offset == notFound) + if (!isValidOffset(offset)) return ResolveGlobalStatus(); return ResolveGlobalStatus(ResolveGlobalStatus::Simple, structure, offset, specificValue); } +#endif // ENABLE(LLINT) || ENABLE(JIT) static ResolveGlobalStatus computeForLLInt(CodeBlock* codeBlock, unsigned bytecodeIndex, Identifier& identifier) { diff --git a/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.h b/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.h index 4698332f7..cbe4d3b5f 100644 --- a/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.h +++ b/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.h @@ -27,6 +27,7 @@ #define ResolveGlobalStatus_h #include "JSValue.h" +#include "PropertyOffset.h" #include <wtf/NotFound.h> namespace JSC { @@ -46,12 +47,12 @@ public: ResolveGlobalStatus() : m_state(NoInformation) , m_structure(0) - , m_offset(notFound) + , m_offset(invalidOffset) { } ResolveGlobalStatus( - State state, Structure* structure = 0, size_t offset = notFound, + State state, Structure* structure = 0, PropertyOffset offset = invalidOffset, JSValue specificValue = JSValue()) : m_state(state) , m_structure(structure) @@ -70,13 +71,13 @@ public: bool takesSlowPath() const { return m_state == TakesSlowPath; } Structure* structure() const { return m_structure; } - size_t offset() const { return m_offset; } + PropertyOffset offset() const { return m_offset; } JSValue specificValue() const { return m_specificValue; } private: State m_state; Structure* m_structure; - size_t m_offset; + PropertyOffset m_offset; JSValue m_specificValue; }; // class ResolveGlobalStatus diff --git a/Source/JavaScriptCore/bytecode/StructureSet.h b/Source/JavaScriptCore/bytecode/StructureSet.h index 2bbc50cad..ebde9779f 100644 --- a/Source/JavaScriptCore/bytecode/StructureSet.h +++ b/Source/JavaScriptCore/bytecode/StructureSet.h @@ -113,15 +113,6 @@ public: size_t size() const { return m_structures.size(); } - bool allAreUsingInlinePropertyStorage() const - { - for (size_t i = 0; i < m_structures.size(); ++i) { - if (!m_structures[i]->isUsingInlineStorage()) - return false; - } - return true; - } - // Call this if you know that the structure set must consist of exactly // one structure. Structure* singletonStructure() const diff --git a/Source/JavaScriptCore/bytecode/StructureStubInfo.h b/Source/JavaScriptCore/bytecode/StructureStubInfo.h index 573f6e975..807966cf3 100644 --- a/Source/JavaScriptCore/bytecode/StructureStubInfo.h +++ b/Source/JavaScriptCore/bytecode/StructureStubInfo.h @@ -32,6 +32,7 @@ #include "CodeOrigin.h" #include "Instruction.h" +#include "JITStubRoutine.h" #include "MacroAssembler.h" #include "Opcode.h" #include "Structure.h" @@ -168,7 +169,7 @@ namespace JSC { { deref(); accessType = access_unset; - stubRoutine = MacroAssemblerCodeRef(); + stubRoutine.clear(); } void deref(); @@ -204,6 +205,7 @@ namespace JSC { int8_t valueGPR; int8_t scratchGPR; int32_t deltaCallToDone; + int32_t deltaCallToStorageLoad; int32_t deltaCallToStructCheck; int32_t deltaCallToSlowCase; int32_t deltaCheckImmToCall; @@ -219,6 +221,7 @@ namespace JSC { struct { int16_t structureToCompare; int16_t structureCheck; + int16_t propertyStorageLoad; #if USE(JSVALUE64) int16_t displacementLabel; #else @@ -230,6 +233,7 @@ namespace JSC { } get; struct { int16_t structureToCompare; + int16_t propertyStorageLoad; #if USE(JSVALUE64) int16_t displacementLabel; #else @@ -283,7 +287,7 @@ namespace JSC { } putByIdList; } u; - MacroAssemblerCodeRef stubRoutine; + RefPtr<JITStubRoutine> stubRoutine; CodeLocationCall callReturnLocation; CodeLocationLabel hotPathBegin; }; |