Changeset 39071 in webkit for trunk/JavaScriptCore/bytecode/JumpTable.cpp
- Timestamp:
- Dec 6, 2008, 2:19:22 PM (16 years ago)
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/bytecode/JumpTable.cpp
r39070 r39071 29 29 30 30 #include "config.h" 31 #include "CodeBlock.h" 32 33 #include "JIT.h" 34 #include "JSValue.h" 35 #include "Interpreter.h" 36 #include "Debugger.h" 37 #include <stdio.h> 38 #include <wtf/StringExtras.h> 31 #include "JumpTable.h" 39 32 40 33 namespace JSC { 41 42 #if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)43 44 static UString escapeQuotes(const UString& str)45 {46 UString result = str;47 int pos = 0;48 while ((pos = result.find('\"', pos)) >= 0) {49 result = result.substr(0, pos) + "\"\\\"\"" + result.substr(pos + 1);50 pos += 4;51 }52 return result;53 }54 55 static UString valueToSourceString(ExecState* exec, JSValue* val)56 {57 if (val->isString()) {58 UString result("\"");59 result += escapeQuotes(val->toString(exec)) + "\"";60 return result;61 }62 63 return val->toString(exec);64 }65 66 static CString registerName(int r)67 {68 if (r == missingThisObjectMarker())69 return "<null>";70 71 return (UString("r") + UString::from(r)).UTF8String();72 }73 74 static CString constantName(ExecState* exec, int k, JSValue* value)75 {76 return (valueToSourceString(exec, value) + "(@k" + UString::from(k) + ")").UTF8String();77 }78 79 static CString idName(int id0, const Identifier& ident)80 {81 return (ident.ustring() + "(@id" + UString::from(id0) +")").UTF8String();82 }83 84 static UString regexpToSourceString(RegExp* regExp)85 {86 UString pattern = UString("/") + regExp->pattern() + "/";87 if (regExp->global())88 pattern += "g";89 if (regExp->ignoreCase())90 pattern += "i";91 if (regExp->multiline())92 pattern += "m";93 94 return pattern;95 }96 97 static CString regexpName(int re, RegExp* regexp)98 {99 return (regexpToSourceString(regexp) + "(@re" + UString::from(re) + ")").UTF8String();100 }101 102 static UString pointerToSourceString(void* p)103 {104 char buffer[2 + 2 * sizeof(void*) + 1]; // 0x [two characters per byte] \0105 snprintf(buffer, sizeof(buffer), "%p", p);106 return buffer;107 }108 109 NEVER_INLINE static const char* debugHookName(int debugHookID)110 {111 switch (static_cast<DebugHookID>(debugHookID)) {112 case DidEnterCallFrame:113 return "didEnterCallFrame";114 case WillLeaveCallFrame:115 return "willLeaveCallFrame";116 case WillExecuteStatement:117 return "willExecuteStatement";118 case WillExecuteProgram:119 return "willExecuteProgram";120 case DidExecuteProgram:121 return "didExecuteProgram";122 case DidReachBreakpoint:123 return "didReachBreakpoint";124 }125 126 ASSERT_NOT_REACHED();127 return "";128 }129 130 static int locationForOffset(const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it, int offset)131 {132 return it - begin + offset;133 }134 135 static void printUnaryOp(int location, Vector<Instruction>::const_iterator& it, const char* op)136 {137 int r0 = (++it)->u.operand;138 int r1 = (++it)->u.operand;139 140 printf("[%4d] %s\t\t %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str());141 }142 143 static void printBinaryOp(int location, Vector<Instruction>::const_iterator& it, const char* op)144 {145 int r0 = (++it)->u.operand;146 int r1 = (++it)->u.operand;147 int r2 = (++it)->u.operand;148 printf("[%4d] %s\t\t %s, %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());149 }150 151 static void printConditionalJump(const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it, int location, const char* op)152 {153 int r0 = (++it)->u.operand;154 int offset = (++it)->u.operand;155 printf("[%4d] %s\t\t %s, %d(->%d)\n", location, op, registerName(r0).c_str(), offset, locationForOffset(begin, it, offset));156 }157 158 static void printGetByIdOp(int location, Vector<Instruction>::const_iterator& it, const Vector<Identifier>& m_identifiers, const char* op)159 {160 int r0 = (++it)->u.operand;161 int r1 = (++it)->u.operand;162 int id0 = (++it)->u.operand;163 printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());164 it += 4;165 }166 167 static void printPutByIdOp(int location, Vector<Instruction>::const_iterator& it, const Vector<Identifier>& m_identifiers, const char* op)168 {169 int r0 = (++it)->u.operand;170 int id0 = (++it)->u.operand;171 int r1 = (++it)->u.operand;172 printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());173 it += 4;174 }175 176 void CodeBlock::printStructure(const char* name, const Instruction* vPC, int operand) const177 {178 unsigned instructionOffset = vPC - m_instructions.begin();179 printf(" [%4d] %s: %s\n", instructionOffset, name, pointerToSourceString(vPC[operand].u.structure).UTF8String().c_str());180 }181 182 void CodeBlock::printStructures(const Instruction* vPC) const183 {184 Interpreter* interpreter = m_globalData->interpreter;185 unsigned instructionOffset = vPC - m_instructions.begin();186 187 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id)) {188 printStructure("get_by_id", vPC, 4);189 return;190 }191 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {192 printStructure("get_by_id_self", vPC, 4);193 return;194 }195 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {196 printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structure).UTF8String().c_str());197 return;198 }199 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {200 printf(" [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_new", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[6].u.structureChain).UTF8String().c_str());201 return;202 }203 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {204 printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structureChain).UTF8String().c_str());205 return;206 }207 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id)) {208 printStructure("put_by_id", vPC, 4);209 return;210 }211 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {212 printStructure("put_by_id_replace", vPC, 4);213 return;214 }215 if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global)) {216 printStructure("resolve_global", vPC, 4);217 return;218 }219 220 // These m_instructions doesn't ref Structures.221 ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_call) || vPC[0].u.opcode == interpreter->getOpcode(op_call_eval) || vPC[0].u.opcode == interpreter->getOpcode(op_construct));222 }223 224 void CodeBlock::dump(ExecState* exec) const225 {226 Vector<Instruction>::const_iterator begin = m_instructions.begin();227 Vector<Instruction>::const_iterator end = m_instructions.end();228 229 size_t instructionCount = 0;230 for (Vector<Instruction>::const_iterator it = begin; it != end; ++it)231 if (exec->interpreter()->isOpcode(it->u.opcode))232 ++instructionCount;233 234 printf("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s)\n\n",235 static_cast<unsigned long>(instructionCount),236 static_cast<unsigned long>(m_instructions.size() * sizeof(Instruction)),237 this, m_numParameters, m_numCalleeRegisters);238 239 for (Vector<Instruction>::const_iterator it = begin; it != end; ++it)240 dump(exec, begin, it);241 242 if (!m_identifiers.isEmpty()) {243 printf("\nIdentifiers:\n");244 size_t i = 0;245 do {246 printf(" id%u = %s\n", static_cast<unsigned>(i), m_identifiers[i].ascii());247 ++i;248 } while (i != m_identifiers.size());249 }250 251 if (!m_constantRegisters.isEmpty()) {252 printf("\nConstants:\n");253 unsigned registerIndex = m_numVars;254 size_t i = 0;255 do {256 printf(" r%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].jsValue(exec)).ascii());257 ++i;258 ++registerIndex;259 } while (i < m_constantRegisters.size());260 }261 262 if (!m_unexpectedConstants.isEmpty()) {263 printf("\nUnexpected Constants:\n");264 size_t i = 0;265 do {266 printf(" k%u = %s\n", static_cast<unsigned>(i), valueToSourceString(exec, m_unexpectedConstants[i]).ascii());267 ++i;268 } while (i < m_unexpectedConstants.size());269 }270 271 if (!m_regexps.isEmpty()) {272 printf("\nm_regexps:\n");273 size_t i = 0;274 do {275 printf(" re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(m_regexps[i].get()).ascii());276 ++i;277 } while (i < m_regexps.size());278 }279 280 if (!m_globalResolveInstructions.isEmpty() || !m_propertyAccessInstructions.isEmpty())281 printf("\nStructures:\n");282 283 if (!m_globalResolveInstructions.isEmpty()) {284 size_t i = 0;285 do {286 printStructures(&m_instructions[m_globalResolveInstructions[i]]);287 ++i;288 } while (i < m_globalResolveInstructions.size());289 }290 if (!m_propertyAccessInstructions.isEmpty()) {291 size_t i = 0;292 do {293 printStructures(&m_instructions[m_propertyAccessInstructions[i].bytecodeIndex]);294 ++i;295 } while (i < m_propertyAccessInstructions.size());296 }297 298 if (!m_exceptionHandlers.isEmpty()) {299 printf("\nException Handlers:\n");300 unsigned i = 0;301 do {302 printf("\t %d: { start: [%4d] end: [%4d] target: [%4d] }\n", i + 1, m_exceptionHandlers[i].start, m_exceptionHandlers[i].end, m_exceptionHandlers[i].target);303 ++i;304 } while (i < m_exceptionHandlers.size());305 }306 307 if (!m_immediateSwitchJumpTables.isEmpty()) {308 printf("Immediate Switch Jump Tables:\n");309 unsigned i = 0;310 do {311 printf(" %1d = {\n", i);312 int entry = 0;313 Vector<int32_t>::const_iterator end = m_immediateSwitchJumpTables[i].branchOffsets.end();314 for (Vector<int32_t>::const_iterator iter = m_immediateSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {315 if (!*iter)316 continue;317 printf("\t\t%4d => %04d\n", entry + m_immediateSwitchJumpTables[i].min, *iter);318 }319 printf(" }\n");320 ++i;321 } while (i < m_immediateSwitchJumpTables.size());322 }323 324 if (!m_characterSwitchJumpTables.isEmpty()) {325 printf("\nCharacter Switch Jump Tables:\n");326 unsigned i = 0;327 do {328 printf(" %1d = {\n", i);329 int entry = 0;330 Vector<int32_t>::const_iterator end = m_characterSwitchJumpTables[i].branchOffsets.end();331 for (Vector<int32_t>::const_iterator iter = m_characterSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {332 if (!*iter)333 continue;334 ASSERT(!((i + m_characterSwitchJumpTables[i].min) & ~0xFFFF));335 UChar ch = static_cast<UChar>(entry + m_characterSwitchJumpTables[i].min);336 printf("\t\t\"%s\" => %04d\n", UString(&ch, 1).ascii(), *iter);337 }338 printf(" }\n");339 ++i;340 } while (i < m_characterSwitchJumpTables.size());341 }342 343 if (!m_stringSwitchJumpTables.isEmpty()) {344 printf("\nString Switch Jump Tables:\n");345 unsigned i = 0;346 do {347 printf(" %1d = {\n", i);348 StringJumpTable::StringOffsetTable::const_iterator end = m_stringSwitchJumpTables[i].offsetTable.end();349 for (StringJumpTable::StringOffsetTable::const_iterator iter = m_stringSwitchJumpTables[i].offsetTable.begin(); iter != end; ++iter)350 printf("\t\t\"%s\" => %04d\n", UString(iter->first).ascii(), iter->second.branchOffset);351 printf(" }\n");352 ++i;353 } while (i < m_stringSwitchJumpTables.size());354 }355 356 printf("\n");357 }358 359 void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it) const360 {361 int location = it - begin;362 switch (exec->interpreter()->getOpcodeID(it->u.opcode)) {363 case op_enter: {364 printf("[%4d] enter\n", location);365 break;366 }367 case op_enter_with_activation: {368 int r0 = (++it)->u.operand;369 printf("[%4d] enter_with_activation %s\n", location, registerName(r0).c_str());370 break;371 }372 case op_create_arguments: {373 printf("[%4d] create_arguments\n", location);374 break;375 }376 case op_convert_this: {377 int r0 = (++it)->u.operand;378 printf("[%4d] convert_this %s\n", location, registerName(r0).c_str());379 break;380 }381 case op_unexpected_load: {382 int r0 = (++it)->u.operand;383 int k0 = (++it)->u.operand;384 printf("[%4d] unexpected_load\t %s, %s\n", location, registerName(r0).c_str(), constantName(exec, k0, m_unexpectedConstants[k0]).c_str());385 break;386 }387 case op_new_object: {388 int r0 = (++it)->u.operand;389 printf("[%4d] new_object\t %s\n", location, registerName(r0).c_str());390 break;391 }392 case op_new_array: {393 int dst = (++it)->u.operand;394 int argv = (++it)->u.operand;395 int argc = (++it)->u.operand;396 printf("[%4d] new_array\t %s, %s, %d\n", location, registerName(dst).c_str(), registerName(argv).c_str(), argc);397 break;398 }399 case op_new_regexp: {400 int r0 = (++it)->u.operand;401 int re0 = (++it)->u.operand;402 printf("[%4d] new_regexp\t %s, %s\n", location, registerName(r0).c_str(), regexpName(re0, m_regexps[re0].get()).c_str());403 break;404 }405 case op_mov: {406 int r0 = (++it)->u.operand;407 int r1 = (++it)->u.operand;408 printf("[%4d] mov\t\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());409 break;410 }411 case op_not: {412 printUnaryOp(location, it, "not");413 break;414 }415 case op_eq: {416 printBinaryOp(location, it, "eq");417 break;418 }419 case op_eq_null: {420 printUnaryOp(location, it, "eq_null");421 break;422 }423 case op_neq: {424 printBinaryOp(location, it, "neq");425 break;426 }427 case op_neq_null: {428 printUnaryOp(location, it, "neq_null");429 break;430 }431 case op_stricteq: {432 printBinaryOp(location, it, "stricteq");433 break;434 }435 case op_nstricteq: {436 printBinaryOp(location, it, "nstricteq");437 break;438 }439 case op_less: {440 printBinaryOp(location, it, "less");441 break;442 }443 case op_lesseq: {444 printBinaryOp(location, it, "lesseq");445 break;446 }447 case op_pre_inc: {448 int r0 = (++it)->u.operand;449 printf("[%4d] pre_inc\t\t %s\n", location, registerName(r0).c_str());450 break;451 }452 case op_pre_dec: {453 int r0 = (++it)->u.operand;454 printf("[%4d] pre_dec\t\t %s\n", location, registerName(r0).c_str());455 break;456 }457 case op_post_inc: {458 printUnaryOp(location, it, "post_inc");459 break;460 }461 case op_post_dec: {462 printUnaryOp(location, it, "post_dec");463 break;464 }465 case op_to_jsnumber: {466 printUnaryOp(location, it, "to_jsnumber");467 break;468 }469 case op_negate: {470 printUnaryOp(location, it, "negate");471 break;472 }473 case op_add: {474 printBinaryOp(location, it, "add");475 ++it;476 break;477 }478 case op_mul: {479 printBinaryOp(location, it, "mul");480 ++it;481 break;482 }483 case op_div: {484 printBinaryOp(location, it, "div");485 break;486 }487 case op_mod: {488 printBinaryOp(location, it, "mod");489 break;490 }491 case op_sub: {492 printBinaryOp(location, it, "sub");493 ++it;494 break;495 }496 case op_lshift: {497 printBinaryOp(location, it, "lshift");498 break;499 }500 case op_rshift: {501 printBinaryOp(location, it, "rshift");502 break;503 }504 case op_urshift: {505 printBinaryOp(location, it, "urshift");506 break;507 }508 case op_bitand: {509 printBinaryOp(location, it, "bitand");510 ++it;511 break;512 }513 case op_bitxor: {514 printBinaryOp(location, it, "bitxor");515 ++it;516 break;517 }518 case op_bitor: {519 printBinaryOp(location, it, "bitor");520 ++it;521 break;522 }523 case op_bitnot: {524 printUnaryOp(location, it, "bitnot");525 break;526 }527 case op_instanceof: {528 int r0 = (++it)->u.operand;529 int r1 = (++it)->u.operand;530 int r2 = (++it)->u.operand;531 int r3 = (++it)->u.operand;532 printf("[%4d] instanceof\t\t %s, %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), registerName(r3).c_str());533 break;534 }535 case op_typeof: {536 printUnaryOp(location, it, "typeof");537 break;538 }539 case op_is_undefined: {540 printUnaryOp(location, it, "is_undefined");541 break;542 }543 case op_is_boolean: {544 printUnaryOp(location, it, "is_boolean");545 break;546 }547 case op_is_number: {548 printUnaryOp(location, it, "is_number");549 break;550 }551 case op_is_string: {552 printUnaryOp(location, it, "is_string");553 break;554 }555 case op_is_object: {556 printUnaryOp(location, it, "is_object");557 break;558 }559 case op_is_function: {560 printUnaryOp(location, it, "is_function");561 break;562 }563 case op_in: {564 printBinaryOp(location, it, "in");565 break;566 }567 case op_resolve: {568 int r0 = (++it)->u.operand;569 int id0 = (++it)->u.operand;570 printf("[%4d] resolve\t\t %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str());571 break;572 }573 case op_resolve_skip: {574 int r0 = (++it)->u.operand;575 int id0 = (++it)->u.operand;576 int skipLevels = (++it)->u.operand;577 printf("[%4d] resolve_skip\t %s, %s, %d\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), skipLevels);578 break;579 }580 case op_resolve_global: {581 int r0 = (++it)->u.operand;582 JSValue* scope = static_cast<JSValue*>((++it)->u.jsCell);583 int id0 = (++it)->u.operand;584 printf("[%4d] resolve_global\t %s, %s, %s\n", location, registerName(r0).c_str(), valueToSourceString(exec, scope).ascii(), idName(id0, m_identifiers[id0]).c_str());585 it += 2;586 break;587 }588 case op_get_scoped_var: {589 int r0 = (++it)->u.operand;590 int index = (++it)->u.operand;591 int skipLevels = (++it)->u.operand;592 printf("[%4d] get_scoped_var\t %s, %d, %d\n", location, registerName(r0).c_str(), index, skipLevels);593 break;594 }595 case op_put_scoped_var: {596 int index = (++it)->u.operand;597 int skipLevels = (++it)->u.operand;598 int r0 = (++it)->u.operand;599 printf("[%4d] put_scoped_var\t %d, %d, %s\n", location, index, skipLevels, registerName(r0).c_str());600 break;601 }602 case op_get_global_var: {603 int r0 = (++it)->u.operand;604 JSValue* scope = static_cast<JSValue*>((++it)->u.jsCell);605 int index = (++it)->u.operand;606 printf("[%4d] get_global_var\t %s, %s, %d\n", location, registerName(r0).c_str(), valueToSourceString(exec, scope).ascii(), index);607 break;608 }609 case op_put_global_var: {610 JSValue* scope = static_cast<JSValue*>((++it)->u.jsCell);611 int index = (++it)->u.operand;612 int r0 = (++it)->u.operand;613 printf("[%4d] put_global_var\t %s, %d, %s\n", location, valueToSourceString(exec, scope).ascii(), index, registerName(r0).c_str());614 break;615 }616 case op_resolve_base: {617 int r0 = (++it)->u.operand;618 int id0 = (++it)->u.operand;619 printf("[%4d] resolve_base\t %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str());620 break;621 }622 case op_resolve_with_base: {623 int r0 = (++it)->u.operand;624 int r1 = (++it)->u.operand;625 int id0 = (++it)->u.operand;626 printf("[%4d] resolve_with_base %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());627 break;628 }629 case op_resolve_func: {630 int r0 = (++it)->u.operand;631 int r1 = (++it)->u.operand;632 int id0 = (++it)->u.operand;633 printf("[%4d] resolve_func\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());634 break;635 }636 case op_get_by_id: {637 printGetByIdOp(location, it, m_identifiers, "get_by_id");638 break;639 }640 case op_get_by_id_self: {641 printGetByIdOp(location, it, m_identifiers, "get_by_id_self");642 break;643 }644 case op_get_by_id_self_list: {645 printGetByIdOp(location, it, m_identifiers, "get_by_id_self_list");646 break;647 }648 case op_get_by_id_proto: {649 printGetByIdOp(location, it, m_identifiers, "get_by_id_proto");650 break;651 }652 case op_get_by_id_proto_list: {653 printGetByIdOp(location, it, m_identifiers, "op_get_by_id_proto_list");654 break;655 }656 case op_get_by_id_chain: {657 printGetByIdOp(location, it, m_identifiers, "get_by_id_chain");658 break;659 }660 case op_get_by_id_generic: {661 printGetByIdOp(location, it, m_identifiers, "get_by_id_generic");662 break;663 }664 case op_get_array_length: {665 printGetByIdOp(location, it, m_identifiers, "get_array_length");666 break;667 }668 case op_get_string_length: {669 printGetByIdOp(location, it, m_identifiers, "get_string_length");670 break;671 }672 case op_put_by_id: {673 printPutByIdOp(location, it, m_identifiers, "put_by_id");674 break;675 }676 case op_put_by_id_replace: {677 printPutByIdOp(location, it, m_identifiers, "put_by_id_replace");678 break;679 }680 case op_put_by_id_transition: {681 printPutByIdOp(location, it, m_identifiers, "put_by_id_transition");682 break;683 }684 case op_put_by_id_generic: {685 printPutByIdOp(location, it, m_identifiers, "put_by_id_generic");686 break;687 }688 case op_put_getter: {689 int r0 = (++it)->u.operand;690 int id0 = (++it)->u.operand;691 int r1 = (++it)->u.operand;692 printf("[%4d] put_getter\t %s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());693 break;694 }695 case op_put_setter: {696 int r0 = (++it)->u.operand;697 int id0 = (++it)->u.operand;698 int r1 = (++it)->u.operand;699 printf("[%4d] put_setter\t %s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());700 break;701 }702 case op_del_by_id: {703 int r0 = (++it)->u.operand;704 int r1 = (++it)->u.operand;705 int id0 = (++it)->u.operand;706 printf("[%4d] del_by_id\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());707 break;708 }709 case op_get_by_val: {710 int r0 = (++it)->u.operand;711 int r1 = (++it)->u.operand;712 int r2 = (++it)->u.operand;713 printf("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());714 break;715 }716 case op_put_by_val: {717 int r0 = (++it)->u.operand;718 int r1 = (++it)->u.operand;719 int r2 = (++it)->u.operand;720 printf("[%4d] put_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());721 break;722 }723 case op_del_by_val: {724 int r0 = (++it)->u.operand;725 int r1 = (++it)->u.operand;726 int r2 = (++it)->u.operand;727 printf("[%4d] del_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());728 break;729 }730 case op_put_by_index: {731 int r0 = (++it)->u.operand;732 unsigned n0 = (++it)->u.operand;733 int r1 = (++it)->u.operand;734 printf("[%4d] put_by_index\t %s, %u, %s\n", location, registerName(r0).c_str(), n0, registerName(r1).c_str());735 break;736 }737 case op_jmp: {738 int offset = (++it)->u.operand;739 printf("[%4d] jmp\t\t %d(->%d)\n", location, offset, locationForOffset(begin, it, offset));740 break;741 }742 case op_loop: {743 int offset = (++it)->u.operand;744 printf("[%4d] loop\t\t %d(->%d)\n", location, offset, locationForOffset(begin, it, offset));745 break;746 }747 case op_jtrue: {748 printConditionalJump(begin, it, location, "jtrue");749 break;750 }751 case op_loop_if_true: {752 printConditionalJump(begin, it, location, "loop_if_true");753 break;754 }755 case op_jfalse: {756 printConditionalJump(begin, it, location, "jfalse");757 break;758 }759 case op_jeq_null: {760 printConditionalJump(begin, it, location, "jeq_null");761 break;762 }763 case op_jneq_null: {764 printConditionalJump(begin, it, location, "jneq_null");765 break;766 }767 case op_jnless: {768 int r0 = (++it)->u.operand;769 int r1 = (++it)->u.operand;770 int offset = (++it)->u.operand;771 printf("[%4d] jnless\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));772 break;773 }774 case op_loop_if_less: {775 int r0 = (++it)->u.operand;776 int r1 = (++it)->u.operand;777 int offset = (++it)->u.operand;778 printf("[%4d] loop_if_less\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));779 break;780 }781 case op_loop_if_lesseq: {782 int r0 = (++it)->u.operand;783 int r1 = (++it)->u.operand;784 int offset = (++it)->u.operand;785 printf("[%4d] loop_if_lesseq\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));786 break;787 }788 case op_switch_imm: {789 int tableIndex = (++it)->u.operand;790 int defaultTarget = (++it)->u.operand;791 int scrutineeRegister = (++it)->u.operand;792 printf("[%4d] switch_imm\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());793 break;794 }795 case op_switch_char: {796 int tableIndex = (++it)->u.operand;797 int defaultTarget = (++it)->u.operand;798 int scrutineeRegister = (++it)->u.operand;799 printf("[%4d] switch_char\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());800 break;801 }802 case op_switch_string: {803 int tableIndex = (++it)->u.operand;804 int defaultTarget = (++it)->u.operand;805 int scrutineeRegister = (++it)->u.operand;806 printf("[%4d] switch_string\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());807 break;808 }809 case op_new_func: {810 int r0 = (++it)->u.operand;811 int f0 = (++it)->u.operand;812 printf("[%4d] new_func\t\t %s, f%d\n", location, registerName(r0).c_str(), f0);813 break;814 }815 case op_new_func_exp: {816 int r0 = (++it)->u.operand;817 int f0 = (++it)->u.operand;818 printf("[%4d] new_func_exp\t %s, f%d\n", location, registerName(r0).c_str(), f0);819 break;820 }821 case op_call: {822 int dst = (++it)->u.operand;823 int func = (++it)->u.operand;824 int argCount = (++it)->u.operand;825 int registerOffset = (++it)->u.operand;826 printf("[%4d] call\t\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset);827 break;828 }829 case op_call_eval: {830 int dst = (++it)->u.operand;831 int func = (++it)->u.operand;832 int argCount = (++it)->u.operand;833 int registerOffset = (++it)->u.operand;834 printf("[%4d] call_eval\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset);835 break;836 }837 case op_tear_off_activation: {838 int r0 = (++it)->u.operand;839 printf("[%4d] tear_off_activation\t %s\n", location, registerName(r0).c_str());840 break;841 }842 case op_tear_off_arguments: {843 printf("[%4d] tear_off_arguments\n", location);844 break;845 }846 case op_ret: {847 int r0 = (++it)->u.operand;848 printf("[%4d] ret\t\t %s\n", location, registerName(r0).c_str());849 break;850 }851 case op_construct: {852 int dst = (++it)->u.operand;853 int func = (++it)->u.operand;854 int argCount = (++it)->u.operand;855 int registerOffset = (++it)->u.operand;856 int proto = (++it)->u.operand;857 int thisRegister = (++it)->u.operand;858 printf("[%4d] construct\t %s, %s, %d, %d, %s, %s\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset, registerName(proto).c_str(), registerName(thisRegister).c_str());859 break;860 }861 case op_construct_verify: {862 int r0 = (++it)->u.operand;863 int r1 = (++it)->u.operand;864 printf("[%4d] construct_verify\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());865 break;866 }867 case op_get_pnames: {868 int r0 = (++it)->u.operand;869 int r1 = (++it)->u.operand;870 printf("[%4d] get_pnames\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());871 break;872 }873 case op_next_pname: {874 int dest = (++it)->u.operand;875 int iter = (++it)->u.operand;876 int offset = (++it)->u.operand;877 printf("[%4d] next_pname\t %s, %s, %d(->%d)\n", location, registerName(dest).c_str(), registerName(iter).c_str(), offset, locationForOffset(begin, it, offset));878 break;879 }880 case op_push_scope: {881 int r0 = (++it)->u.operand;882 printf("[%4d] push_scope\t %s\n", location, registerName(r0).c_str());883 break;884 }885 case op_pop_scope: {886 printf("[%4d] pop_scope\n", location);887 break;888 }889 case op_push_new_scope: {890 int r0 = (++it)->u.operand;891 int id0 = (++it)->u.operand;892 int r1 = (++it)->u.operand;893 printf("[%4d] push_new_scope \t%s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());894 break;895 }896 case op_jmp_scopes: {897 int scopeDelta = (++it)->u.operand;898 int offset = (++it)->u.operand;899 printf("[%4d] jmp_scopes\t^%d, %d(->%d)\n", location, scopeDelta, offset, locationForOffset(begin, it, offset));900 break;901 }902 case op_catch: {903 int r0 = (++it)->u.operand;904 printf("[%4d] catch\t\t %s\n", location, registerName(r0).c_str());905 break;906 }907 case op_throw: {908 int r0 = (++it)->u.operand;909 printf("[%4d] throw\t\t %s\n", location, registerName(r0).c_str());910 break;911 }912 case op_new_error: {913 int r0 = (++it)->u.operand;914 int errorType = (++it)->u.operand;915 int k0 = (++it)->u.operand;916 printf("[%4d] new_error\t %s, %d, %s\n", location, registerName(r0).c_str(), errorType, constantName(exec, k0, m_unexpectedConstants[k0]).c_str());917 break;918 }919 case op_jsr: {920 int retAddrDst = (++it)->u.operand;921 int offset = (++it)->u.operand;922 printf("[%4d] jsr\t\t %s, %d(->%d)\n", location, registerName(retAddrDst).c_str(), offset, locationForOffset(begin, it, offset));923 break;924 }925 case op_sret: {926 int retAddrSrc = (++it)->u.operand;927 printf("[%4d] sret\t\t %s\n", location, registerName(retAddrSrc).c_str());928 break;929 }930 case op_debug: {931 int debugHookID = (++it)->u.operand;932 int firstLine = (++it)->u.operand;933 int lastLine = (++it)->u.operand;934 printf("[%4d] debug\t\t %s, %d, %d\n", location, debugHookName(debugHookID), firstLine, lastLine);935 break;936 }937 case op_profile_will_call: {938 int function = (++it)->u.operand;939 printf("[%4d] profile_will_call %s\n", location, registerName(function).c_str());940 break;941 }942 case op_profile_did_call: {943 int function = (++it)->u.operand;944 printf("[%4d] profile_did_call\t %s\n", location, registerName(function).c_str());945 break;946 }947 case op_end: {948 int r0 = (++it)->u.operand;949 printf("[%4d] end\t\t %s\n", location, registerName(r0).c_str());950 break;951 }952 }953 }954 955 #endif // !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)956 957 CodeBlock::~CodeBlock()958 {959 for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i)960 derefStructures(&m_instructions[m_globalResolveInstructions[i]]);961 962 for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i) {963 derefStructures(&m_instructions[m_propertyAccessInstructions[i].bytecodeIndex]);964 if (m_propertyAccessInstructions[i].stubRoutine)965 WTF::fastFreeExecutable(m_propertyAccessInstructions[i].stubRoutine);966 }967 968 for (size_t size = m_callLinkInfos.size(), i = 0; i < size; ++i) {969 CallLinkInfo* callLinkInfo = &m_callLinkInfos[i];970 if (callLinkInfo->isLinked())971 callLinkInfo->callee->removeCaller(callLinkInfo);972 }973 974 #if ENABLE(JIT)975 unlinkCallers();976 977 if (m_jitCode)978 WTF::fastFreeExecutable(m_jitCode);979 #endif980 }981 982 #if ENABLE(JIT)983 void CodeBlock::unlinkCallers()984 {985 size_t size = m_linkedCallerList.size();986 for (size_t i = 0; i < size; ++i) {987 CallLinkInfo* currentCaller = m_linkedCallerList[i];988 JIT::unlinkCall(currentCaller);989 currentCaller->setUnlinked();990 }991 m_linkedCallerList.clear();992 }993 #endif994 995 void CodeBlock::derefStructures(Instruction* vPC) const996 {997 Interpreter* interpreter = m_globalData->interpreter;998 999 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {1000 vPC[4].u.structure->deref();1001 return;1002 }1003 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {1004 vPC[4].u.structure->deref();1005 vPC[5].u.structure->deref();1006 return;1007 }1008 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {1009 vPC[4].u.structure->deref();1010 vPC[5].u.structureChain->deref();1011 return;1012 }1013 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {1014 vPC[4].u.structure->deref();1015 vPC[5].u.structure->deref();1016 vPC[6].u.structureChain->deref();1017 return;1018 }1019 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {1020 vPC[4].u.structure->deref();1021 return;1022 }1023 if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global)) {1024 if(vPC[4].u.structure)1025 vPC[4].u.structure->deref();1026 return;1027 }1028 if ((vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto_list))1029 || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self_list))) {1030 PolymorphicAccessStructureList* polymorphicStructures = vPC[4].u.polymorphicStructures;1031 polymorphicStructures->derefStructures(vPC[5].u.operand);1032 delete polymorphicStructures;1033 return;1034 }1035 1036 // These instructions don't ref their Structures.1037 ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_get_array_length) || vPC[0].u.opcode == interpreter->getOpcode(op_get_string_length));1038 }1039 1040 void CodeBlock::refStructures(Instruction* vPC) const1041 {1042 Interpreter* interpreter = m_globalData->interpreter;1043 1044 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {1045 vPC[4].u.structure->ref();1046 return;1047 }1048 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {1049 vPC[4].u.structure->ref();1050 vPC[5].u.structure->ref();1051 return;1052 }1053 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {1054 vPC[4].u.structure->ref();1055 vPC[5].u.structureChain->ref();1056 return;1057 }1058 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {1059 vPC[4].u.structure->ref();1060 vPC[5].u.structure->ref();1061 vPC[6].u.structureChain->ref();1062 return;1063 }1064 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {1065 vPC[4].u.structure->ref();1066 return;1067 }1068 1069 // These instructions don't ref their Structures.1070 ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic));1071 }1072 1073 void CodeBlock::mark()1074 {1075 for (size_t i = 0; i < m_constantRegisters.size(); ++i)1076 if (!m_constantRegisters[i].marked())1077 m_constantRegisters[i].mark();1078 1079 for (size_t i = 0; i < m_unexpectedConstants.size(); ++i)1080 if (!m_unexpectedConstants[i]->marked())1081 m_unexpectedConstants[i]->mark();1082 1083 for (size_t i = 0; i < m_functions.size(); ++i)1084 m_functions[i]->body()->mark();1085 1086 for (size_t i = 0; i < m_functionExpressions.size(); ++i)1087 m_functionExpressions[i]->body()->mark();1088 }1089 1090 bool CodeBlock::getHandlerForVPC(const Instruction* vPC, Instruction*& target, int& scopeDepth)1091 {1092 Vector<HandlerInfo>::iterator ptr = m_exceptionHandlers.begin();1093 Vector<HandlerInfo>::iterator end = m_exceptionHandlers.end();1094 unsigned addressOffset = vPC - m_instructions.begin();1095 ASSERT(addressOffset < m_instructions.size());1096 1097 for (; ptr != end; ++ptr) {1098 // Handlers are ordered innermost first, so the first handler we encounter1099 // that contains the source address is the correct handler to use.1100 if (ptr->start <= addressOffset && ptr->end >= addressOffset) {1101 scopeDepth = ptr->scopeDepth;1102 target = m_instructions.begin() + ptr->target;1103 return true;1104 }1105 }1106 return false;1107 }1108 1109 void* CodeBlock::nativeExceptionCodeForHandlerVPC(const Instruction* handlerVPC)1110 {1111 Vector<HandlerInfo>::iterator ptr = m_exceptionHandlers.begin();1112 Vector<HandlerInfo>::iterator end = m_exceptionHandlers.end();1113 1114 for (; ptr != end; ++ptr) {1115 Instruction*target = m_instructions.begin() + ptr->target;1116 if (handlerVPC == target)1117 return ptr->nativeCode;1118 }1119 1120 return 0;1121 }1122 1123 int CodeBlock::lineNumberForVPC(const Instruction* vPC)1124 {1125 unsigned instructionOffset = vPC - m_instructions.begin();1126 ASSERT(instructionOffset < m_instructions.size());1127 1128 if (!m_lineInfo.size())1129 return m_ownerNode->source().firstLine(); // Empty function1130 1131 int low = 0;1132 int high = m_lineInfo.size();1133 while (low < high) {1134 int mid = low + (high - low) / 2;1135 if (m_lineInfo[mid].instructionOffset <= instructionOffset)1136 low = mid + 1;1137 else1138 high = mid;1139 }1140 1141 if (!low)1142 return m_ownerNode->source().firstLine();1143 return m_lineInfo[low - 1].lineNumber;1144 }1145 1146 int CodeBlock::expressionRangeForVPC(const Instruction* vPC, int& divot, int& startOffset, int& endOffset)1147 {1148 unsigned instructionOffset = vPC - m_instructions.begin();1149 ASSERT(instructionOffset < m_instructions.size());1150 1151 if (!m_expressionInfo.size()) {1152 // We didn't think anything could throw. Apparently we were wrong.1153 startOffset = 0;1154 endOffset = 0;1155 divot = 0;1156 return lineNumberForVPC(vPC);1157 }1158 1159 int low = 0;1160 int high = m_expressionInfo.size();1161 while (low < high) {1162 int mid = low + (high - low) / 2;1163 if (m_expressionInfo[mid].instructionOffset <= instructionOffset)1164 low = mid + 1;1165 else1166 high = mid;1167 }1168 1169 ASSERT(low);1170 if (!low) {1171 startOffset = 0;1172 endOffset = 0;1173 divot = 0;1174 return lineNumberForVPC(vPC);1175 }1176 1177 startOffset = m_expressionInfo[low - 1].startOffset;1178 endOffset = m_expressionInfo[low - 1].endOffset;1179 divot = m_expressionInfo[low - 1].divotPoint + m_sourceOffset;1180 return lineNumberForVPC(vPC);1181 }1182 1183 void CodeBlock::shrinkToFit()1184 {1185 m_instructions.shrinkToFit();1186 1187 m_globalResolveInstructions.shrinkToFit();1188 m_propertyAccessInstructions.shrinkToFit();1189 m_callLinkInfos.shrinkToFit();1190 m_linkedCallerList.shrinkToFit();1191 1192 m_exceptionHandlers.shrinkToFit();1193 m_expressionInfo.shrinkToFit();1194 m_lineInfo.shrinkToFit();1195 1196 m_identifiers.shrinkToFit();1197 m_functions.shrinkToFit();1198 m_functionExpressions.shrinkToFit();1199 m_constantRegisters.shrinkToFit();1200 m_unexpectedConstants.shrinkToFit();1201 m_regexps.shrinkToFit();1202 1203 m_immediateSwitchJumpTables.shrinkToFit();1204 m_characterSwitchJumpTables.shrinkToFit();1205 m_stringSwitchJumpTables.shrinkToFit();1206 }1207 34 1208 35 int32_t SimpleJumpTable::offsetForValue(int32_t value, int32_t defaultOffset)
Note:
See TracChangeset
for help on using the changeset viewer.