Changeset 39229 in webkit for trunk/JavaScriptCore/bytecode/StructureStubInfo.cpp
- Timestamp:
- Dec 12, 2008, 12:02:09 AM (16 years ago)
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/bytecode/StructureStubInfo.cpp
r39218 r39229 1 1 /* 2 2 * Copyright (C) 2008 Apple Inc. All rights reserved. 3 * Copyright (C) 2008 Cameron Zwarich <[email protected]>4 3 * 5 4 * Redistribution and use in source and binary forms, with or without 6 5 * modification, are permitted provided that the following conditions 7 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 8 12 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 15 * its contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 24 */ 29 25 30 26 #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> 39 40 #define DUMP_CODE_BLOCK_STATISTICS 0 27 #include "StructureStubInfo.h" 41 28 42 29 namespace JSC { 43 30 44 #if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING) 45 46 static UString escapeQuotes(const UString& str) 31 #if ENABLE(JIT) 32 void StructureStubInfo::deref() 47 33 { 48 UString result = str; 49 int pos = 0; 50 while ((pos = result.find('\"', pos)) >= 0) { 51 result = result.substr(0, pos) + "\"\\\"\"" + result.substr(pos + 1); 52 pos += 4; 53 } 54 return result; 55 } 56 57 static UString valueToSourceString(ExecState* exec, JSValue* val) 58 { 59 if (val->isString()) { 60 UString result("\""); 61 result += escapeQuotes(val->toString(exec)) + "\""; 62 return result; 63 } 64 65 return val->toString(exec); 66 } 67 68 static CString registerName(int r) 69 { 70 if (r == missingThisObjectMarker()) 71 return "<null>"; 72 73 return (UString("r") + UString::from(r)).UTF8String(); 74 } 75 76 static CString constantName(ExecState* exec, int k, JSValue* value) 77 { 78 return (valueToSourceString(exec, value) + "(@k" + UString::from(k) + ")").UTF8String(); 79 } 80 81 static CString idName(int id0, const Identifier& ident) 82 { 83 return (ident.ustring() + "(@id" + UString::from(id0) +")").UTF8String(); 84 } 85 86 static UString regexpToSourceString(RegExp* regExp) 87 { 88 UString pattern = UString("/") + regExp->pattern() + "/"; 89 if (regExp->global()) 90 pattern += "g"; 91 if (regExp->ignoreCase()) 92 pattern += "i"; 93 if (regExp->multiline()) 94 pattern += "m"; 95 96 return pattern; 97 } 98 99 static CString regexpName(int re, RegExp* regexp) 100 { 101 return (regexpToSourceString(regexp) + "(@re" + UString::from(re) + ")").UTF8String(); 102 } 103 104 static UString pointerToSourceString(void* p) 105 { 106 char buffer[2 + 2 * sizeof(void*) + 1]; // 0x [two characters per byte] \0 107 snprintf(buffer, sizeof(buffer), "%p", p); 108 return buffer; 109 } 110 111 NEVER_INLINE static const char* debugHookName(int debugHookID) 112 { 113 switch (static_cast<DebugHookID>(debugHookID)) { 114 case DidEnterCallFrame: 115 return "didEnterCallFrame"; 116 case WillLeaveCallFrame: 117 return "willLeaveCallFrame"; 118 case WillExecuteStatement: 119 return "willExecuteStatement"; 120 case WillExecuteProgram: 121 return "willExecuteProgram"; 122 case DidExecuteProgram: 123 return "didExecuteProgram"; 124 case DidReachBreakpoint: 125 return "didReachBreakpoint"; 126 } 127 128 ASSERT_NOT_REACHED(); 129 return ""; 130 } 131 132 static int locationForOffset(const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it, int offset) 133 { 134 return it - begin + offset; 135 } 136 137 static void printUnaryOp(int location, Vector<Instruction>::const_iterator& it, const char* op) 138 { 139 int r0 = (++it)->u.operand; 140 int r1 = (++it)->u.operand; 141 142 printf("[%4d] %s\t\t %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str()); 143 } 144 145 static void printBinaryOp(int location, Vector<Instruction>::const_iterator& it, const char* op) 146 { 147 int r0 = (++it)->u.operand; 148 int r1 = (++it)->u.operand; 149 int r2 = (++it)->u.operand; 150 printf("[%4d] %s\t\t %s, %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str()); 151 } 152 153 static void printConditionalJump(const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it, int location, const char* op) 154 { 155 int r0 = (++it)->u.operand; 156 int offset = (++it)->u.operand; 157 printf("[%4d] %s\t\t %s, %d(->%d)\n", location, op, registerName(r0).c_str(), offset, locationForOffset(begin, it, offset)); 158 } 159 160 static void printGetByIdOp(int location, Vector<Instruction>::const_iterator& it, const Vector<Identifier>& m_identifiers, const char* op) 161 { 162 int r0 = (++it)->u.operand; 163 int r1 = (++it)->u.operand; 164 int id0 = (++it)->u.operand; 165 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()); 166 it += 4; 167 } 168 169 static void printPutByIdOp(int location, Vector<Instruction>::const_iterator& it, const Vector<Identifier>& m_identifiers, const char* op) 170 { 171 int r0 = (++it)->u.operand; 172 int id0 = (++it)->u.operand; 173 int r1 = (++it)->u.operand; 174 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()); 175 it += 4; 176 } 177 178 void CodeBlock::printStructure(const char* name, const Instruction* vPC, int operand) const 179 { 180 unsigned instructionOffset = vPC - m_instructions.begin(); 181 printf(" [%4d] %s: %s\n", instructionOffset, name, pointerToSourceString(vPC[operand].u.structure).UTF8String().c_str()); 182 } 183 184 void CodeBlock::printStructures(const Instruction* vPC) const 185 { 186 Interpreter* interpreter = m_globalData->interpreter; 187 unsigned instructionOffset = vPC - m_instructions.begin(); 188 189 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id)) { 190 printStructure("get_by_id", vPC, 4); 34 switch (opcodeID) { 35 case op_get_by_id_self: 36 u.getByIdSelf.baseObjectStructure->deref(); 37 return; 38 case op_get_by_id_proto: 39 u.getByIdProto.baseObjectStructure->deref(); 40 u.getByIdProto.prototypeStructure->deref(); 41 return; 42 case op_get_by_id_chain: 43 u.getByIdChain.baseObjectStructure->deref(); 44 u.getByIdChain.chain->deref(); 45 return; 46 case op_get_by_id_self_list: { 47 PolymorphicAccessStructureList* polymorphicStructures = u.getByIdSelfList.structureList; 48 polymorphicStructures->derefStructures(u.getByIdSelfList.listSize); 49 delete polymorphicStructures; 191 50 return; 192 51 } 193 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) { 194 printStructure("get_by_id_self", vPC, 4); 52 case op_get_by_id_proto_list: { 53 PolymorphicAccessStructureList* polymorphicStructures = u.getByIdProtoList.structureList; 54 polymorphicStructures->derefStructures(u.getByIdProtoList.listSize); 55 delete polymorphicStructures; 195 56 return; 196 57 } 197 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) { 198 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()); 58 case op_put_by_id_transition: 59 u.putByIdTransition.previousStructure->deref(); 60 u.putByIdTransition.structure->deref(); 61 u.putByIdTransition.chain->deref(); 199 62 return; 63 case op_put_by_id_replace: 64 u.putByIdReplace.baseObjectStructure->deref(); 65 return; 66 case op_get_by_id: 67 case op_put_by_id: 68 case op_get_by_id_generic: 69 case op_put_by_id_generic: 70 case op_get_array_length: 71 case op_get_string_length: 72 // These instructions don't ref their Structures. 73 return; 74 default: 75 ASSERT_NOT_REACHED(); 200 76 } 201 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {202 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());203 return;204 }205 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {206 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());207 return;208 }209 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id)) {210 printStructure("put_by_id", vPC, 4);211 return;212 }213 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {214 printStructure("put_by_id_replace", vPC, 4);215 return;216 }217 if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global)) {218 printStructure("resolve_global", vPC, 4);219 return;220 }221 222 // These m_instructions doesn't ref Structures.223 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));224 }225 226 void CodeBlock::dump(ExecState* exec) const227 {228 Vector<Instruction>::const_iterator begin = m_instructions.begin();229 Vector<Instruction>::const_iterator end = m_instructions.end();230 231 size_t instructionCount = 0;232 for (Vector<Instruction>::const_iterator it = begin; it != end; ++it)233 if (exec->interpreter()->isOpcode(it->u.opcode))234 ++instructionCount;235 236 printf("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s)\n\n",237 static_cast<unsigned long>(instructionCount),238 static_cast<unsigned long>(m_instructions.size() * sizeof(Instruction)),239 this, m_numParameters, m_numCalleeRegisters);240 241 for (Vector<Instruction>::const_iterator it = begin; it != end; ++it)242 dump(exec, begin, it);243 244 if (!m_identifiers.isEmpty()) {245 printf("\nIdentifiers:\n");246 size_t i = 0;247 do {248 printf(" id%u = %s\n", static_cast<unsigned>(i), m_identifiers[i].ascii());249 ++i;250 } while (i != m_identifiers.size());251 }252 253 if (!m_constantRegisters.isEmpty()) {254 printf("\nConstants:\n");255 unsigned registerIndex = m_numVars;256 size_t i = 0;257 do {258 printf(" r%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].jsValue(exec)).ascii());259 ++i;260 ++registerIndex;261 } while (i < m_constantRegisters.size());262 }263 264 if (m_rareData && !m_rareData->m_unexpectedConstants.isEmpty()) {265 printf("\nUnexpected Constants:\n");266 size_t i = 0;267 do {268 printf(" k%u = %s\n", static_cast<unsigned>(i), valueToSourceString(exec, m_rareData->m_unexpectedConstants[i]).ascii());269 ++i;270 } while (i < m_rareData->m_unexpectedConstants.size());271 }272 273 if (m_rareData && !m_rareData->m_regexps.isEmpty()) {274 printf("\nm_regexps:\n");275 size_t i = 0;276 do {277 printf(" re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(m_rareData->m_regexps[i].get()).ascii());278 ++i;279 } while (i < m_rareData->m_regexps.size());280 }281 282 if (!m_globalResolveInstructions.isEmpty() || !m_propertyAccessInstructions.isEmpty())283 printf("\nStructures:\n");284 285 if (!m_globalResolveInstructions.isEmpty()) {286 size_t i = 0;287 do {288 printStructures(&m_instructions[m_globalResolveInstructions[i]]);289 ++i;290 } while (i < m_globalResolveInstructions.size());291 }292 if (!m_propertyAccessInstructions.isEmpty()) {293 size_t i = 0;294 do {295 printStructures(&m_instructions[m_propertyAccessInstructions[i].bytecodeIndex]);296 ++i;297 } while (i < m_propertyAccessInstructions.size());298 }299 300 if (m_rareData && !m_rareData->m_exceptionHandlers.isEmpty()) {301 printf("\nException Handlers:\n");302 unsigned i = 0;303 do {304 printf("\t %d: { start: [%4d] end: [%4d] target: [%4d] }\n", i + 1, m_rareData->m_exceptionHandlers[i].start, m_rareData->m_exceptionHandlers[i].end, m_rareData->m_exceptionHandlers[i].target);305 ++i;306 } while (i < m_rareData->m_exceptionHandlers.size());307 }308 309 if (m_rareData && !m_rareData->m_immediateSwitchJumpTables.isEmpty()) {310 printf("Immediate Switch Jump Tables:\n");311 unsigned i = 0;312 do {313 printf(" %1d = {\n", i);314 int entry = 0;315 Vector<int32_t>::const_iterator end = m_rareData->m_immediateSwitchJumpTables[i].branchOffsets.end();316 for (Vector<int32_t>::const_iterator iter = m_rareData->m_immediateSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {317 if (!*iter)318 continue;319 printf("\t\t%4d => %04d\n", entry + m_rareData->m_immediateSwitchJumpTables[i].min, *iter);320 }321 printf(" }\n");322 ++i;323 } while (i < m_rareData->m_immediateSwitchJumpTables.size());324 }325 326 if (m_rareData && !m_rareData->m_characterSwitchJumpTables.isEmpty()) {327 printf("\nCharacter Switch Jump Tables:\n");328 unsigned i = 0;329 do {330 printf(" %1d = {\n", i);331 int entry = 0;332 Vector<int32_t>::const_iterator end = m_rareData->m_characterSwitchJumpTables[i].branchOffsets.end();333 for (Vector<int32_t>::const_iterator iter = m_rareData->m_characterSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {334 if (!*iter)335 continue;336 ASSERT(!((i + m_rareData->m_characterSwitchJumpTables[i].min) & ~0xFFFF));337 UChar ch = static_cast<UChar>(entry + m_rareData->m_characterSwitchJumpTables[i].min);338 printf("\t\t\"%s\" => %04d\n", UString(&ch, 1).ascii(), *iter);339 }340 printf(" }\n");341 ++i;342 } while (i < m_rareData->m_characterSwitchJumpTables.size());343 }344 345 if (m_rareData && !m_rareData->m_stringSwitchJumpTables.isEmpty()) {346 printf("\nString Switch Jump Tables:\n");347 unsigned i = 0;348 do {349 printf(" %1d = {\n", i);350 StringJumpTable::StringOffsetTable::const_iterator end = m_rareData->m_stringSwitchJumpTables[i].offsetTable.end();351 for (StringJumpTable::StringOffsetTable::const_iterator iter = m_rareData->m_stringSwitchJumpTables[i].offsetTable.begin(); iter != end; ++iter)352 printf("\t\t\"%s\" => %04d\n", UString(iter->first).ascii(), iter->second.branchOffset);353 printf(" }\n");354 ++i;355 } while (i < m_rareData->m_stringSwitchJumpTables.size());356 }357 358 printf("\n");359 }360 361 void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it) const362 {363 int location = it - begin;364 switch (exec->interpreter()->getOpcodeID(it->u.opcode)) {365 case op_enter: {366 printf("[%4d] enter\n", location);367 break;368 }369 case op_enter_with_activation: {370 int r0 = (++it)->u.operand;371 printf("[%4d] enter_with_activation %s\n", location, registerName(r0).c_str());372 break;373 }374 case op_create_arguments: {375 printf("[%4d] create_arguments\n", location);376 break;377 }378 case op_convert_this: {379 int r0 = (++it)->u.operand;380 printf("[%4d] convert_this %s\n", location, registerName(r0).c_str());381 break;382 }383 case op_unexpected_load: {384 int r0 = (++it)->u.operand;385 int k0 = (++it)->u.operand;386 printf("[%4d] unexpected_load\t %s, %s\n", location, registerName(r0).c_str(), constantName(exec, k0, unexpectedConstant(k0)).c_str());387 break;388 }389 case op_new_object: {390 int r0 = (++it)->u.operand;391 printf("[%4d] new_object\t %s\n", location, registerName(r0).c_str());392 break;393 }394 case op_new_array: {395 int dst = (++it)->u.operand;396 int argv = (++it)->u.operand;397 int argc = (++it)->u.operand;398 printf("[%4d] new_array\t %s, %s, %d\n", location, registerName(dst).c_str(), registerName(argv).c_str(), argc);399 break;400 }401 case op_new_regexp: {402 int r0 = (++it)->u.operand;403 int re0 = (++it)->u.operand;404 printf("[%4d] new_regexp\t %s, %s\n", location, registerName(r0).c_str(), regexpName(re0, regexp(re0)).c_str());405 break;406 }407 case op_mov: {408 int r0 = (++it)->u.operand;409 int r1 = (++it)->u.operand;410 printf("[%4d] mov\t\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());411 break;412 }413 case op_not: {414 printUnaryOp(location, it, "not");415 break;416 }417 case op_eq: {418 printBinaryOp(location, it, "eq");419 break;420 }421 case op_eq_null: {422 printUnaryOp(location, it, "eq_null");423 break;424 }425 case op_neq: {426 printBinaryOp(location, it, "neq");427 break;428 }429 case op_neq_null: {430 printUnaryOp(location, it, "neq_null");431 break;432 }433 case op_stricteq: {434 printBinaryOp(location, it, "stricteq");435 break;436 }437 case op_nstricteq: {438 printBinaryOp(location, it, "nstricteq");439 break;440 }441 case op_less: {442 printBinaryOp(location, it, "less");443 break;444 }445 case op_lesseq: {446 printBinaryOp(location, it, "lesseq");447 break;448 }449 case op_pre_inc: {450 int r0 = (++it)->u.operand;451 printf("[%4d] pre_inc\t\t %s\n", location, registerName(r0).c_str());452 break;453 }454 case op_pre_dec: {455 int r0 = (++it)->u.operand;456 printf("[%4d] pre_dec\t\t %s\n", location, registerName(r0).c_str());457 break;458 }459 case op_post_inc: {460 printUnaryOp(location, it, "post_inc");461 break;462 }463 case op_post_dec: {464 printUnaryOp(location, it, "post_dec");465 break;466 }467 case op_to_jsnumber: {468 printUnaryOp(location, it, "to_jsnumber");469 break;470 }471 case op_negate: {472 printUnaryOp(location, it, "negate");473 break;474 }475 case op_add: {476 printBinaryOp(location, it, "add");477 ++it;478 break;479 }480 case op_mul: {481 printBinaryOp(location, it, "mul");482 ++it;483 break;484 }485 case op_div: {486 printBinaryOp(location, it, "div");487 break;488 }489 case op_mod: {490 printBinaryOp(location, it, "mod");491 break;492 }493 case op_sub: {494 printBinaryOp(location, it, "sub");495 ++it;496 break;497 }498 case op_lshift: {499 printBinaryOp(location, it, "lshift");500 break;501 }502 case op_rshift: {503 printBinaryOp(location, it, "rshift");504 break;505 }506 case op_urshift: {507 printBinaryOp(location, it, "urshift");508 break;509 }510 case op_bitand: {511 printBinaryOp(location, it, "bitand");512 ++it;513 break;514 }515 case op_bitxor: {516 printBinaryOp(location, it, "bitxor");517 ++it;518 break;519 }520 case op_bitor: {521 printBinaryOp(location, it, "bitor");522 ++it;523 break;524 }525 case op_bitnot: {526 printUnaryOp(location, it, "bitnot");527 break;528 }529 case op_instanceof: {530 int r0 = (++it)->u.operand;531 int r1 = (++it)->u.operand;532 int r2 = (++it)->u.operand;533 int r3 = (++it)->u.operand;534 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());535 break;536 }537 case op_typeof: {538 printUnaryOp(location, it, "typeof");539 break;540 }541 case op_is_undefined: {542 printUnaryOp(location, it, "is_undefined");543 break;544 }545 case op_is_boolean: {546 printUnaryOp(location, it, "is_boolean");547 break;548 }549 case op_is_number: {550 printUnaryOp(location, it, "is_number");551 break;552 }553 case op_is_string: {554 printUnaryOp(location, it, "is_string");555 break;556 }557 case op_is_object: {558 printUnaryOp(location, it, "is_object");559 break;560 }561 case op_is_function: {562 printUnaryOp(location, it, "is_function");563 break;564 }565 case op_in: {566 printBinaryOp(location, it, "in");567 break;568 }569 case op_resolve: {570 int r0 = (++it)->u.operand;571 int id0 = (++it)->u.operand;572 printf("[%4d] resolve\t\t %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str());573 break;574 }575 case op_resolve_skip: {576 int r0 = (++it)->u.operand;577 int id0 = (++it)->u.operand;578 int skipLevels = (++it)->u.operand;579 printf("[%4d] resolve_skip\t %s, %s, %d\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), skipLevels);580 break;581 }582 case op_resolve_global: {583 int r0 = (++it)->u.operand;584 JSValue* scope = static_cast<JSValue*>((++it)->u.jsCell);585 int id0 = (++it)->u.operand;586 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());587 it += 2;588 break;589 }590 case op_get_scoped_var: {591 int r0 = (++it)->u.operand;592 int index = (++it)->u.operand;593 int skipLevels = (++it)->u.operand;594 printf("[%4d] get_scoped_var\t %s, %d, %d\n", location, registerName(r0).c_str(), index, skipLevels);595 break;596 }597 case op_put_scoped_var: {598 int index = (++it)->u.operand;599 int skipLevels = (++it)->u.operand;600 int r0 = (++it)->u.operand;601 printf("[%4d] put_scoped_var\t %d, %d, %s\n", location, index, skipLevels, registerName(r0).c_str());602 break;603 }604 case op_get_global_var: {605 int r0 = (++it)->u.operand;606 JSValue* scope = static_cast<JSValue*>((++it)->u.jsCell);607 int index = (++it)->u.operand;608 printf("[%4d] get_global_var\t %s, %s, %d\n", location, registerName(r0).c_str(), valueToSourceString(exec, scope).ascii(), index);609 break;610 }611 case op_put_global_var: {612 JSValue* scope = static_cast<JSValue*>((++it)->u.jsCell);613 int index = (++it)->u.operand;614 int r0 = (++it)->u.operand;615 printf("[%4d] put_global_var\t %s, %d, %s\n", location, valueToSourceString(exec, scope).ascii(), index, registerName(r0).c_str());616 break;617 }618 case op_resolve_base: {619 int r0 = (++it)->u.operand;620 int id0 = (++it)->u.operand;621 printf("[%4d] resolve_base\t %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str());622 break;623 }624 case op_resolve_with_base: {625 int r0 = (++it)->u.operand;626 int r1 = (++it)->u.operand;627 int id0 = (++it)->u.operand;628 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());629 break;630 }631 case op_resolve_func: {632 int r0 = (++it)->u.operand;633 int r1 = (++it)->u.operand;634 int id0 = (++it)->u.operand;635 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());636 break;637 }638 case op_get_by_id: {639 printGetByIdOp(location, it, m_identifiers, "get_by_id");640 break;641 }642 case op_get_by_id_self: {643 printGetByIdOp(location, it, m_identifiers, "get_by_id_self");644 break;645 }646 case op_get_by_id_self_list: {647 printGetByIdOp(location, it, m_identifiers, "get_by_id_self_list");648 break;649 }650 case op_get_by_id_proto: {651 printGetByIdOp(location, it, m_identifiers, "get_by_id_proto");652 break;653 }654 case op_get_by_id_proto_list: {655 printGetByIdOp(location, it, m_identifiers, "op_get_by_id_proto_list");656 break;657 }658 case op_get_by_id_chain: {659 printGetByIdOp(location, it, m_identifiers, "get_by_id_chain");660 break;661 }662 case op_get_by_id_generic: {663 printGetByIdOp(location, it, m_identifiers, "get_by_id_generic");664 break;665 }666 case op_get_array_length: {667 printGetByIdOp(location, it, m_identifiers, "get_array_length");668 break;669 }670 case op_get_string_length: {671 printGetByIdOp(location, it, m_identifiers, "get_string_length");672 break;673 }674 case op_put_by_id: {675 printPutByIdOp(location, it, m_identifiers, "put_by_id");676 break;677 }678 case op_put_by_id_replace: {679 printPutByIdOp(location, it, m_identifiers, "put_by_id_replace");680 break;681 }682 case op_put_by_id_transition: {683 printPutByIdOp(location, it, m_identifiers, "put_by_id_transition");684 break;685 }686 case op_put_by_id_generic: {687 printPutByIdOp(location, it, m_identifiers, "put_by_id_generic");688 break;689 }690 case op_put_getter: {691 int r0 = (++it)->u.operand;692 int id0 = (++it)->u.operand;693 int r1 = (++it)->u.operand;694 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());695 break;696 }697 case op_put_setter: {698 int r0 = (++it)->u.operand;699 int id0 = (++it)->u.operand;700 int r1 = (++it)->u.operand;701 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());702 break;703 }704 case op_del_by_id: {705 int r0 = (++it)->u.operand;706 int r1 = (++it)->u.operand;707 int id0 = (++it)->u.operand;708 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());709 break;710 }711 case op_get_by_val: {712 int r0 = (++it)->u.operand;713 int r1 = (++it)->u.operand;714 int r2 = (++it)->u.operand;715 printf("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());716 break;717 }718 case op_put_by_val: {719 int r0 = (++it)->u.operand;720 int r1 = (++it)->u.operand;721 int r2 = (++it)->u.operand;722 printf("[%4d] put_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());723 break;724 }725 case op_del_by_val: {726 int r0 = (++it)->u.operand;727 int r1 = (++it)->u.operand;728 int r2 = (++it)->u.operand;729 printf("[%4d] del_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());730 break;731 }732 case op_put_by_index: {733 int r0 = (++it)->u.operand;734 unsigned n0 = (++it)->u.operand;735 int r1 = (++it)->u.operand;736 printf("[%4d] put_by_index\t %s, %u, %s\n", location, registerName(r0).c_str(), n0, registerName(r1).c_str());737 break;738 }739 case op_jmp: {740 int offset = (++it)->u.operand;741 printf("[%4d] jmp\t\t %d(->%d)\n", location, offset, locationForOffset(begin, it, offset));742 break;743 }744 case op_loop: {745 int offset = (++it)->u.operand;746 printf("[%4d] loop\t\t %d(->%d)\n", location, offset, locationForOffset(begin, it, offset));747 break;748 }749 case op_jtrue: {750 printConditionalJump(begin, it, location, "jtrue");751 break;752 }753 case op_loop_if_true: {754 printConditionalJump(begin, it, location, "loop_if_true");755 break;756 }757 case op_jfalse: {758 printConditionalJump(begin, it, location, "jfalse");759 break;760 }761 case op_jeq_null: {762 printConditionalJump(begin, it, location, "jeq_null");763 break;764 }765 case op_jneq_null: {766 printConditionalJump(begin, it, location, "jneq_null");767 break;768 }769 case op_jnless: {770 int r0 = (++it)->u.operand;771 int r1 = (++it)->u.operand;772 int offset = (++it)->u.operand;773 printf("[%4d] jnless\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));774 break;775 }776 case op_loop_if_less: {777 int r0 = (++it)->u.operand;778 int r1 = (++it)->u.operand;779 int offset = (++it)->u.operand;780 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));781 break;782 }783 case op_loop_if_lesseq: {784 int r0 = (++it)->u.operand;785 int r1 = (++it)->u.operand;786 int offset = (++it)->u.operand;787 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));788 break;789 }790 case op_switch_imm: {791 int tableIndex = (++it)->u.operand;792 int defaultTarget = (++it)->u.operand;793 int scrutineeRegister = (++it)->u.operand;794 printf("[%4d] switch_imm\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());795 break;796 }797 case op_switch_char: {798 int tableIndex = (++it)->u.operand;799 int defaultTarget = (++it)->u.operand;800 int scrutineeRegister = (++it)->u.operand;801 printf("[%4d] switch_char\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());802 break;803 }804 case op_switch_string: {805 int tableIndex = (++it)->u.operand;806 int defaultTarget = (++it)->u.operand;807 int scrutineeRegister = (++it)->u.operand;808 printf("[%4d] switch_string\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());809 break;810 }811 case op_new_func: {812 int r0 = (++it)->u.operand;813 int f0 = (++it)->u.operand;814 printf("[%4d] new_func\t\t %s, f%d\n", location, registerName(r0).c_str(), f0);815 break;816 }817 case op_new_func_exp: {818 int r0 = (++it)->u.operand;819 int f0 = (++it)->u.operand;820 printf("[%4d] new_func_exp\t %s, f%d\n", location, registerName(r0).c_str(), f0);821 break;822 }823 case op_call: {824 int dst = (++it)->u.operand;825 int func = (++it)->u.operand;826 int argCount = (++it)->u.operand;827 int registerOffset = (++it)->u.operand;828 printf("[%4d] call\t\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset);829 break;830 }831 case op_call_eval: {832 int dst = (++it)->u.operand;833 int func = (++it)->u.operand;834 int argCount = (++it)->u.operand;835 int registerOffset = (++it)->u.operand;836 printf("[%4d] call_eval\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset);837 break;838 }839 case op_tear_off_activation: {840 int r0 = (++it)->u.operand;841 printf("[%4d] tear_off_activation\t %s\n", location, registerName(r0).c_str());842 break;843 }844 case op_tear_off_arguments: {845 printf("[%4d] tear_off_arguments\n", location);846 break;847 }848 case op_ret: {849 int r0 = (++it)->u.operand;850 printf("[%4d] ret\t\t %s\n", location, registerName(r0).c_str());851 break;852 }853 case op_construct: {854 int dst = (++it)->u.operand;855 int func = (++it)->u.operand;856 int argCount = (++it)->u.operand;857 int registerOffset = (++it)->u.operand;858 int proto = (++it)->u.operand;859 int thisRegister = (++it)->u.operand;860 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());861 break;862 }863 case op_construct_verify: {864 int r0 = (++it)->u.operand;865 int r1 = (++it)->u.operand;866 printf("[%4d] construct_verify\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());867 break;868 }869 case op_get_pnames: {870 int r0 = (++it)->u.operand;871 int r1 = (++it)->u.operand;872 printf("[%4d] get_pnames\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());873 break;874 }875 case op_next_pname: {876 int dest = (++it)->u.operand;877 int iter = (++it)->u.operand;878 int offset = (++it)->u.operand;879 printf("[%4d] next_pname\t %s, %s, %d(->%d)\n", location, registerName(dest).c_str(), registerName(iter).c_str(), offset, locationForOffset(begin, it, offset));880 break;881 }882 case op_push_scope: {883 int r0 = (++it)->u.operand;884 printf("[%4d] push_scope\t %s\n", location, registerName(r0).c_str());885 break;886 }887 case op_pop_scope: {888 printf("[%4d] pop_scope\n", location);889 break;890 }891 case op_push_new_scope: {892 int r0 = (++it)->u.operand;893 int id0 = (++it)->u.operand;894 int r1 = (++it)->u.operand;895 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());896 break;897 }898 case op_jmp_scopes: {899 int scopeDelta = (++it)->u.operand;900 int offset = (++it)->u.operand;901 printf("[%4d] jmp_scopes\t^%d, %d(->%d)\n", location, scopeDelta, offset, locationForOffset(begin, it, offset));902 break;903 }904 case op_catch: {905 int r0 = (++it)->u.operand;906 printf("[%4d] catch\t\t %s\n", location, registerName(r0).c_str());907 break;908 }909 case op_throw: {910 int r0 = (++it)->u.operand;911 printf("[%4d] throw\t\t %s\n", location, registerName(r0).c_str());912 break;913 }914 case op_new_error: {915 int r0 = (++it)->u.operand;916 int errorType = (++it)->u.operand;917 int k0 = (++it)->u.operand;918 printf("[%4d] new_error\t %s, %d, %s\n", location, registerName(r0).c_str(), errorType, constantName(exec, k0, unexpectedConstant(k0)).c_str());919 break;920 }921 case op_jsr: {922 int retAddrDst = (++it)->u.operand;923 int offset = (++it)->u.operand;924 printf("[%4d] jsr\t\t %s, %d(->%d)\n", location, registerName(retAddrDst).c_str(), offset, locationForOffset(begin, it, offset));925 break;926 }927 case op_sret: {928 int retAddrSrc = (++it)->u.operand;929 printf("[%4d] sret\t\t %s\n", location, registerName(retAddrSrc).c_str());930 break;931 }932 case op_debug: {933 int debugHookID = (++it)->u.operand;934 int firstLine = (++it)->u.operand;935 int lastLine = (++it)->u.operand;936 printf("[%4d] debug\t\t %s, %d, %d\n", location, debugHookName(debugHookID), firstLine, lastLine);937 break;938 }939 case op_profile_will_call: {940 int function = (++it)->u.operand;941 printf("[%4d] profile_will_call %s\n", location, registerName(function).c_str());942 break;943 }944 case op_profile_did_call: {945 int function = (++it)->u.operand;946 printf("[%4d] profile_did_call\t %s\n", location, registerName(function).c_str());947 break;948 }949 case op_end: {950 int r0 = (++it)->u.operand;951 printf("[%4d] end\t\t %s\n", location, registerName(r0).c_str());952 break;953 }954 }955 }956 957 #endif // !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)958 959 #if DUMP_CODE_BLOCK_STATISTICS960 static HashSet<CodeBlock*> liveCodeBlockSet;961 #endif962 963 #define FOR_EACH_MEMBER_VECTOR(macro) \964 macro(instructions) \965 macro(globalResolveInstructions) \966 macro(propertyAccessInstructions) \967 macro(callLinkInfos) \968 macro(linkedCallerList) \969 macro(identifiers) \970 macro(functionExpressions) \971 macro(constantRegisters) \972 macro(expressionInfo) \973 macro(lineInfo) \974 macro(pcVector)975 976 #define FOR_EACH_MEMBER_VECTOR_RARE_DATA(macro) \977 macro(regexps) \978 macro(functions) \979 macro(unexpectedConstants) \980 macro(exceptionHandlers) \981 macro(immediateSwitchJumpTables) \982 macro(characterSwitchJumpTables) \983 macro(stringSwitchJumpTables)984 985 template<typename T>986 static size_t sizeInBytes(const Vector<T>& vector)987 {988 return vector.capacity() * sizeof(T);989 }990 991 void CodeBlock::dumpStatistics()992 {993 #if DUMP_CODE_BLOCK_STATISTICS994 #define DEFINE_VARS(name) size_t name##IsNotEmpty = 0; size_t name##TotalSize = 0;995 FOR_EACH_MEMBER_VECTOR(DEFINE_VARS)996 FOR_EACH_MEMBER_VECTOR_RARE_DATA(DEFINE_VARS)997 #undef DEFINE_VARS998 999 // Non-vector data members1000 size_t evalCodeCacheIsNotEmpty = 0;1001 1002 size_t symbolTableIsNotEmpty = 0;1003 size_t symbolTableTotalSize = 0;1004 1005 size_t hasRareData = 0;1006 1007 HashSet<CodeBlock*>::const_iterator end = liveCodeBlockSet.end();1008 for (HashSet<CodeBlock*>::const_iterator it = liveCodeBlockSet.begin(); it != end; ++it) {1009 CodeBlock* codeBlock = *it;1010 1011 #define GET_STATS(name) if (!codeBlock->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_##name); }1012 FOR_EACH_MEMBER_VECTOR(GET_STATS)1013 #undef GET_STATS1014 1015 if (!codeBlock->m_symbolTable.isEmpty()) {1016 symbolTableIsNotEmpty++;1017 symbolTableTotalSize += (codeBlock->m_symbolTable.capacity() * (sizeof(SymbolTable::KeyType) + sizeof(SymbolTable::MappedType)));1018 }1019 1020 if (codeBlock->m_rareData) {1021 hasRareData++;1022 #define GET_STATS(name) if (!codeBlock->m_rareData->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_rareData->m_##name); }1023 FOR_EACH_MEMBER_VECTOR_RARE_DATA(GET_STATS)1024 #undef GET_STATS1025 1026 if (!codeBlock->m_rareData->m_evalCodeCache.isEmpty())1027 evalCodeCacheIsNotEmpty++;1028 }1029 }1030 1031 printf("Number of live CodeBlocks: %d\n", liveCodeBlockSet.size());1032 printf("Size of a single CodeBlock [sizeof(CodeBlock)]: %zu\n", sizeof(CodeBlock));1033 1034 printf("Number of CodeBlocks with rare data: %zu\n", hasRareData);1035 1036 #define PRINT_STATS(name) printf("Number of CodeBlocks with " #name ": %zu\n", name##IsNotEmpty); printf("Size of all " #name ": %zu\n", name##TotalSize);1037 FOR_EACH_MEMBER_VECTOR(PRINT_STATS)1038 FOR_EACH_MEMBER_VECTOR_RARE_DATA(PRINT_STATS)1039 #undef PRINT_STATS1040 1041 printf("Number of CodeBlocks with evalCodeCache: %zu\n", evalCodeCacheIsNotEmpty);1042 printf("Number of CodeBlocks with symbolTable: %zu\n", symbolTableIsNotEmpty);1043 1044 printf("Size of all symbolTables: %zu\n", symbolTableTotalSize);1045 1046 #else1047 printf("Dumping CodeBlock statistics is not enabled.\n");1048 #endif1049 }1050 1051 1052 CodeBlock::CodeBlock(ScopeNode* ownerNode, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset)1053 : m_numCalleeRegisters(0)1054 , m_numConstants(0)1055 , m_numVars(0)1056 , m_numParameters(0)1057 , m_ownerNode(ownerNode)1058 , m_globalData(0)1059 #if ENABLE(JIT)1060 , m_jitCode(0)1061 #endif1062 , m_needsFullScopeChain(ownerNode->needsActivation())1063 , m_usesEval(ownerNode->usesEval())1064 , m_codeType(codeType)1065 , m_source(sourceProvider)1066 , m_sourceOffset(sourceOffset)1067 {1068 ASSERT(m_source);1069 1070 #if DUMP_CODE_BLOCK_STATISTICS1071 liveCodeBlockSet.add(this);1072 #endif1073 }1074 1075 CodeBlock::~CodeBlock()1076 {1077 for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i)1078 derefStructures(&m_instructions[m_globalResolveInstructions[i]]);1079 1080 for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i) {1081 derefStructures(&m_instructions[m_propertyAccessInstructions[i].bytecodeIndex]);1082 }1083 1084 for (size_t size = m_callLinkInfos.size(), i = 0; i < size; ++i) {1085 CallLinkInfo* callLinkInfo = &m_callLinkInfos[i];1086 if (callLinkInfo->isLinked())1087 callLinkInfo->callee->removeCaller(callLinkInfo);1088 }1089 1090 #if ENABLE(JIT)1091 unlinkCallers();1092 #endif1093 1094 #if DUMP_CODE_BLOCK_STATISTICS1095 liveCodeBlockSet.remove(this);1096 #endif1097 }1098 1099 #if ENABLE(JIT)1100 void CodeBlock::unlinkCallers()1101 {1102 size_t size = m_linkedCallerList.size();1103 for (size_t i = 0; i < size; ++i) {1104 CallLinkInfo* currentCaller = m_linkedCallerList[i];1105 JIT::unlinkCall(currentCaller);1106 currentCaller->setUnlinked();1107 }1108 m_linkedCallerList.clear();1109 77 } 1110 78 #endif 1111 79 1112 void CodeBlock::derefStructures(Instruction* vPC) const1113 {1114 Interpreter* interpreter = m_globalData->interpreter;1115 1116 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {1117 vPC[4].u.structure->deref();1118 return;1119 }1120 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {1121 vPC[4].u.structure->deref();1122 vPC[5].u.structure->deref();1123 return;1124 }1125 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {1126 vPC[4].u.structure->deref();1127 vPC[5].u.structureChain->deref();1128 return;1129 }1130 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {1131 vPC[4].u.structure->deref();1132 vPC[5].u.structure->deref();1133 vPC[6].u.structureChain->deref();1134 return;1135 }1136 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {1137 vPC[4].u.structure->deref();1138 return;1139 }1140 if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global)) {1141 if(vPC[4].u.structure)1142 vPC[4].u.structure->deref();1143 return;1144 }1145 if ((vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto_list))1146 || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self_list))) {1147 PolymorphicAccessStructureList* polymorphicStructures = vPC[4].u.polymorphicStructures;1148 polymorphicStructures->derefStructures(vPC[5].u.operand);1149 delete polymorphicStructures;1150 return;1151 }1152 1153 // These instructions don't ref their Structures.1154 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));1155 }1156 1157 void CodeBlock::refStructures(Instruction* vPC) const1158 {1159 Interpreter* interpreter = m_globalData->interpreter;1160 1161 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {1162 vPC[4].u.structure->ref();1163 return;1164 }1165 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {1166 vPC[4].u.structure->ref();1167 vPC[5].u.structure->ref();1168 return;1169 }1170 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {1171 vPC[4].u.structure->ref();1172 vPC[5].u.structureChain->ref();1173 return;1174 }1175 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {1176 vPC[4].u.structure->ref();1177 vPC[5].u.structure->ref();1178 vPC[6].u.structureChain->ref();1179 return;1180 }1181 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {1182 vPC[4].u.structure->ref();1183 return;1184 }1185 1186 // These instructions don't ref their Structures.1187 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));1188 }1189 1190 void CodeBlock::mark()1191 {1192 for (size_t i = 0; i < m_constantRegisters.size(); ++i)1193 if (!m_constantRegisters[i].marked())1194 m_constantRegisters[i].mark();1195 1196 for (size_t i = 0; i < m_functionExpressions.size(); ++i)1197 m_functionExpressions[i]->body()->mark();1198 1199 if (m_rareData) {1200 for (size_t i = 0; i < m_rareData->m_functions.size(); ++i)1201 m_rareData->m_functions[i]->body()->mark();1202 1203 for (size_t i = 0; i < m_rareData->m_unexpectedConstants.size(); ++i) {1204 if (!m_rareData->m_unexpectedConstants[i]->marked())1205 m_rareData->m_unexpectedConstants[i]->mark();1206 }1207 }1208 }1209 1210 HandlerInfo* CodeBlock::handlerForVPC(const Instruction* vPC)1211 {1212 if (!m_rareData)1213 return 0;1214 1215 unsigned addressOffset = vPC - m_instructions.begin();1216 ASSERT(addressOffset < m_instructions.size());1217 1218 Vector<HandlerInfo>& exceptionHandlers = m_rareData->m_exceptionHandlers;1219 for (size_t i = 0; i < exceptionHandlers.size(); ++i) {1220 // Handlers are ordered innermost first, so the first handler we encounter1221 // that contains the source address is the correct handler to use.1222 if (exceptionHandlers[i].start <= addressOffset && exceptionHandlers[i].end >= addressOffset)1223 return &exceptionHandlers[i];1224 }1225 1226 return 0;1227 }1228 1229 int CodeBlock::lineNumberForVPC(const Instruction* vPC)1230 {1231 unsigned instructionOffset = vPC - m_instructions.begin();1232 ASSERT(instructionOffset < m_instructions.size());1233 1234 if (!m_lineInfo.size())1235 return m_ownerNode->source().firstLine(); // Empty function1236 1237 int low = 0;1238 int high = m_lineInfo.size();1239 while (low < high) {1240 int mid = low + (high - low) / 2;1241 if (m_lineInfo[mid].instructionOffset <= instructionOffset)1242 low = mid + 1;1243 else1244 high = mid;1245 }1246 1247 if (!low)1248 return m_ownerNode->source().firstLine();1249 return m_lineInfo[low - 1].lineNumber;1250 }1251 1252 int CodeBlock::expressionRangeForVPC(const Instruction* vPC, int& divot, int& startOffset, int& endOffset)1253 {1254 unsigned instructionOffset = vPC - m_instructions.begin();1255 ASSERT(instructionOffset < m_instructions.size());1256 1257 if (!m_expressionInfo.size()) {1258 // We didn't think anything could throw. Apparently we were wrong.1259 startOffset = 0;1260 endOffset = 0;1261 divot = 0;1262 return lineNumberForVPC(vPC);1263 }1264 1265 int low = 0;1266 int high = m_expressionInfo.size();1267 while (low < high) {1268 int mid = low + (high - low) / 2;1269 if (m_expressionInfo[mid].instructionOffset <= instructionOffset)1270 low = mid + 1;1271 else1272 high = mid;1273 }1274 1275 ASSERT(low);1276 if (!low) {1277 startOffset = 0;1278 endOffset = 0;1279 divot = 0;1280 return lineNumberForVPC(vPC);1281 }1282 1283 startOffset = m_expressionInfo[low - 1].startOffset;1284 endOffset = m_expressionInfo[low - 1].endOffset;1285 divot = m_expressionInfo[low - 1].divotPoint + m_sourceOffset;1286 return lineNumberForVPC(vPC);1287 }1288 1289 void CodeBlock::shrinkToFit()1290 {1291 m_instructions.shrinkToFit();1292 1293 m_globalResolveInstructions.shrinkToFit();1294 m_propertyAccessInstructions.shrinkToFit();1295 m_callLinkInfos.shrinkToFit();1296 m_linkedCallerList.shrinkToFit();1297 m_expressionInfo.shrinkToFit();1298 m_lineInfo.shrinkToFit();1299 m_identifiers.shrinkToFit();1300 m_functionExpressions.shrinkToFit();1301 m_constantRegisters.shrinkToFit();1302 1303 if (m_rareData) {1304 m_rareData->m_exceptionHandlers.shrinkToFit();1305 m_rareData->m_functions.shrinkToFit();1306 m_rareData->m_unexpectedConstants.shrinkToFit();1307 m_rareData->m_regexps.shrinkToFit();1308 m_rareData->m_immediateSwitchJumpTables.shrinkToFit();1309 m_rareData->m_characterSwitchJumpTables.shrinkToFit();1310 m_rareData->m_stringSwitchJumpTables.shrinkToFit();1311 }1312 }1313 1314 80 } // namespace JSC
Note:
See TracChangeset
for help on using the changeset viewer.