summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/bytecode
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-07-11 13:45:28 +0200
committerSimon Hausmann <simon.hausmann@nokia.com>2012-07-11 13:45:28 +0200
commitd6a599dbc9d824a462b2b206316e102bf8136446 (patch)
treeecb257a5e55b2239d74b90fdad62fccd661cf286 /Source/JavaScriptCore/bytecode
parent3ccc3a85f09a83557b391aae380d3bf5f81a2911 (diff)
downloadqtwebkit-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')
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.cpp391
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.h165
-rw-r--r--Source/JavaScriptCore/bytecode/Comment.h37
-rw-r--r--Source/JavaScriptCore/bytecode/DataFormat.h9
-rw-r--r--Source/JavaScriptCore/bytecode/ExecutionCounter.cpp8
-rw-r--r--Source/JavaScriptCore/bytecode/ExecutionCounter.h14
-rw-r--r--Source/JavaScriptCore/bytecode/GetByIdStatus.cpp24
-rw-r--r--Source/JavaScriptCore/bytecode/GetByIdStatus.h9
-rw-r--r--Source/JavaScriptCore/bytecode/Instruction.h17
-rw-r--r--Source/JavaScriptCore/bytecode/Opcode.h4
-rw-r--r--Source/JavaScriptCore/bytecode/Operands.h50
-rw-r--r--Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.cpp2
-rw-r--r--Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.h10
-rw-r--r--Source/JavaScriptCore/bytecode/PutByIdStatus.cpp41
-rw-r--r--Source/JavaScriptCore/bytecode/PutByIdStatus.h11
-rw-r--r--Source/JavaScriptCore/bytecode/ResolveGlobalStatus.cpp6
-rw-r--r--Source/JavaScriptCore/bytecode/ResolveGlobalStatus.h9
-rw-r--r--Source/JavaScriptCore/bytecode/StructureSet.h9
-rw-r--r--Source/JavaScriptCore/bytecode/StructureStubInfo.h8
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;
};