1/* 2 * Copyright (C) 2008, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved. 3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 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. 28 */ 29 30#include "config.h" 31#include "CodeBlock.h" 32 33#include "BytecodeGenerator.h" 34#include "CallLinkStatus.h" 35#include "DFGCapabilities.h" 36#include "DFGCommon.h" 37#include "DFGNode.h" 38#include "DFGRepatch.h" 39#include "Debugger.h" 40#include "Interpreter.h" 41#include "JIT.h" 42#include "JITStubs.h" 43#include "JSActivation.h" 44#include "JSCJSValue.h" 45#include "JSFunction.h" 46#include "JSNameScope.h" 47#include "LowLevelInterpreter.h" 48#include "Operations.h" 49#include "ReduceWhitespace.h" 50#include "RepatchBuffer.h" 51#include "SlotVisitorInlines.h" 52#include <stdio.h> 53#include <wtf/CommaPrinter.h> 54#include <wtf/StringExtras.h> 55#include <wtf/StringPrintStream.h> 56 57#if ENABLE(DFG_JIT) 58#include "DFGOperations.h" 59#endif 60 61#define DUMP_CODE_BLOCK_STATISTICS 0 62 63namespace JSC { 64 65#if ENABLE(DFG_JIT) 66using namespace DFG; 67#endif 68 69String CodeBlock::inferredName() const 70{ 71 switch (codeType()) { 72 case GlobalCode: 73 return "<global>"; 74 case EvalCode: 75 return "<eval>"; 76 case FunctionCode: 77 return jsCast<FunctionExecutable*>(ownerExecutable())->inferredName().string(); 78 default: 79 CRASH(); 80 return String(); 81 } 82} 83 84CodeBlockHash CodeBlock::hash() const 85{ 86 return CodeBlockHash(ownerExecutable()->source(), specializationKind()); 87} 88 89String CodeBlock::sourceCodeForTools() const 90{ 91 if (codeType() != FunctionCode) 92 return ownerExecutable()->source().toString(); 93 94 SourceProvider* provider = source(); 95 FunctionExecutable* executable = jsCast<FunctionExecutable*>(ownerExecutable()); 96 UnlinkedFunctionExecutable* unlinked = executable->unlinkedExecutable(); 97 unsigned unlinkedStartOffset = unlinked->startOffset(); 98 unsigned linkedStartOffset = executable->source().startOffset(); 99 int delta = linkedStartOffset - unlinkedStartOffset; 100 StringBuilder builder; 101 builder.append("function "); 102 builder.append(provider->getRange( 103 delta + unlinked->functionStartOffset(), 104 delta + unlinked->startOffset() + unlinked->sourceLength())); 105 return builder.toString(); 106} 107 108String CodeBlock::sourceCodeOnOneLine() const 109{ 110 return reduceWhitespace(sourceCodeForTools()); 111} 112 113void CodeBlock::dumpAssumingJITType(PrintStream& out, JITCode::JITType jitType) const 114{ 115 out.print(inferredName(), "#", hash(), ":[", RawPointer(this), "->", RawPointer(ownerExecutable()), ", ", jitType, codeType()); 116 if (codeType() == FunctionCode) 117 out.print(specializationKind()); 118 out.print("]"); 119} 120 121void CodeBlock::dump(PrintStream& out) const 122{ 123 dumpAssumingJITType(out, getJITType()); 124} 125 126static String escapeQuotes(const String& str) 127{ 128 String result = str; 129 size_t pos = 0; 130 while ((pos = result.find('\"', pos)) != notFound) { 131 result = makeString(result.substringSharingImpl(0, pos), "\"\\\"\"", result.substringSharingImpl(pos + 1)); 132 pos += 4; 133 } 134 return result; 135} 136 137static String valueToSourceString(ExecState* exec, JSValue val) 138{ 139 if (!val) 140 return ASCIILiteral("0"); 141 142 if (val.isString()) 143 return makeString("\"", escapeQuotes(val.toString(exec)->value(exec)), "\""); 144 145 return toString(val); 146} 147 148static CString constantName(ExecState* exec, int k, JSValue value) 149{ 150 return makeString(valueToSourceString(exec, value), "(@k", String::number(k - FirstConstantRegisterIndex), ")").utf8(); 151} 152 153static CString idName(int id0, const Identifier& ident) 154{ 155 return makeString(ident.string(), "(@id", String::number(id0), ")").utf8(); 156} 157 158CString CodeBlock::registerName(ExecState* exec, int r) const 159{ 160 if (r == missingThisObjectMarker()) 161 return "<null>"; 162 163 if (isConstantRegisterIndex(r)) 164 return constantName(exec, r, getConstant(r)); 165 166 return makeString("r", String::number(r)).utf8(); 167} 168 169static String regexpToSourceString(RegExp* regExp) 170{ 171 char postfix[5] = { '/', 0, 0, 0, 0 }; 172 int index = 1; 173 if (regExp->global()) 174 postfix[index++] = 'g'; 175 if (regExp->ignoreCase()) 176 postfix[index++] = 'i'; 177 if (regExp->multiline()) 178 postfix[index] = 'm'; 179 180 return makeString("/", regExp->pattern(), postfix); 181} 182 183static CString regexpName(int re, RegExp* regexp) 184{ 185 return makeString(regexpToSourceString(regexp), "(@re", String::number(re), ")").utf8(); 186} 187 188static String pointerToSourceString(void* p) 189{ 190 char buffer[2 + 2 * sizeof(void*) + 1]; // 0x [two characters per byte] \0 191 snprintf(buffer, sizeof(buffer), "%p", p); 192 return buffer; 193} 194 195NEVER_INLINE static const char* debugHookName(int debugHookID) 196{ 197 switch (static_cast<DebugHookID>(debugHookID)) { 198 case DidEnterCallFrame: 199 return "didEnterCallFrame"; 200 case WillLeaveCallFrame: 201 return "willLeaveCallFrame"; 202 case WillExecuteStatement: 203 return "willExecuteStatement"; 204 case WillExecuteProgram: 205 return "willExecuteProgram"; 206 case DidExecuteProgram: 207 return "didExecuteProgram"; 208 case DidReachBreakpoint: 209 return "didReachBreakpoint"; 210 } 211 212 RELEASE_ASSERT_NOT_REACHED(); 213 return ""; 214} 215 216void CodeBlock::printUnaryOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op) 217{ 218 int r0 = (++it)->u.operand; 219 int r1 = (++it)->u.operand; 220 221 out.printf("[%4d] %s\t\t %s, %s", location, op, registerName(exec, r0).data(), registerName(exec, r1).data()); 222} 223 224void CodeBlock::printBinaryOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op) 225{ 226 int r0 = (++it)->u.operand; 227 int r1 = (++it)->u.operand; 228 int r2 = (++it)->u.operand; 229 out.printf("[%4d] %s\t\t %s, %s, %s", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); 230} 231 232void CodeBlock::printConditionalJump(PrintStream& out, ExecState* exec, const Instruction*, const Instruction*& it, int location, const char* op) 233{ 234 int r0 = (++it)->u.operand; 235 int offset = (++it)->u.operand; 236 out.printf("[%4d] %s\t\t %s, %d(->%d)", location, op, registerName(exec, r0).data(), offset, location + offset); 237} 238 239void CodeBlock::printGetByIdOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it) 240{ 241 const char* op; 242 switch (exec->interpreter()->getOpcodeID(it->u.opcode)) { 243 case op_get_by_id: 244 op = "get_by_id"; 245 break; 246 case op_get_by_id_out_of_line: 247 op = "get_by_id_out_of_line"; 248 break; 249 case op_get_by_id_self: 250 op = "get_by_id_self"; 251 break; 252 case op_get_by_id_proto: 253 op = "get_by_id_proto"; 254 break; 255 case op_get_by_id_chain: 256 op = "get_by_id_chain"; 257 break; 258 case op_get_by_id_getter_self: 259 op = "get_by_id_getter_self"; 260 break; 261 case op_get_by_id_getter_proto: 262 op = "get_by_id_getter_proto"; 263 break; 264 case op_get_by_id_getter_chain: 265 op = "get_by_id_getter_chain"; 266 break; 267 case op_get_by_id_custom_self: 268 op = "get_by_id_custom_self"; 269 break; 270 case op_get_by_id_custom_proto: 271 op = "get_by_id_custom_proto"; 272 break; 273 case op_get_by_id_custom_chain: 274 op = "get_by_id_custom_chain"; 275 break; 276 case op_get_by_id_generic: 277 op = "get_by_id_generic"; 278 break; 279 case op_get_array_length: 280 op = "array_length"; 281 break; 282 case op_get_string_length: 283 op = "string_length"; 284 break; 285 default: 286 RELEASE_ASSERT_NOT_REACHED(); 287 op = 0; 288 } 289 int r0 = (++it)->u.operand; 290 int r1 = (++it)->u.operand; 291 int id0 = (++it)->u.operand; 292 out.printf("[%4d] %s\t %s, %s, %s", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data()); 293 it += 4; // Increment up to the value profiler. 294} 295 296#if ENABLE(JIT) || ENABLE(LLINT) // unused in some configurations 297static void dumpStructure(PrintStream& out, const char* name, ExecState* exec, Structure* structure, Identifier& ident) 298{ 299 if (!structure) 300 return; 301 302 out.printf("%s = %p", name, structure); 303 304 PropertyOffset offset = structure->get(exec->vm(), ident); 305 if (offset != invalidOffset) 306 out.printf(" (offset = %d)", offset); 307} 308#endif 309 310#if ENABLE(JIT) // unused when not ENABLE(JIT), leading to silly warnings 311static void dumpChain(PrintStream& out, ExecState* exec, StructureChain* chain, Identifier& ident) 312{ 313 out.printf("chain = %p: [", chain); 314 bool first = true; 315 for (WriteBarrier<Structure>* currentStructure = chain->head(); 316 *currentStructure; 317 ++currentStructure) { 318 if (first) 319 first = false; 320 else 321 out.printf(", "); 322 dumpStructure(out, "struct", exec, currentStructure->get(), ident); 323 } 324 out.printf("]"); 325} 326#endif 327 328void CodeBlock::printGetByIdCacheStatus(PrintStream& out, ExecState* exec, int location) 329{ 330 Instruction* instruction = instructions().begin() + location; 331 332 Identifier& ident = identifier(instruction[3].u.operand); 333 334 UNUSED_PARAM(ident); // tell the compiler to shut up in certain platform configurations. 335 336#if ENABLE(LLINT) 337 if (exec->interpreter()->getOpcodeID(instruction[0].u.opcode) == op_get_array_length) 338 out.printf(" llint(array_length)"); 339 else if (Structure* structure = instruction[4].u.structure.get()) { 340 out.printf(" llint("); 341 dumpStructure(out, "struct", exec, structure, ident); 342 out.printf(")"); 343 } 344#endif 345 346#if ENABLE(JIT) 347 if (numberOfStructureStubInfos()) { 348 StructureStubInfo& stubInfo = getStubInfo(location); 349 if (stubInfo.seen) { 350 out.printf(" jit("); 351 352 Structure* baseStructure = 0; 353 Structure* prototypeStructure = 0; 354 StructureChain* chain = 0; 355 PolymorphicAccessStructureList* structureList = 0; 356 int listSize = 0; 357 358 switch (stubInfo.accessType) { 359 case access_get_by_id_self: 360 out.printf("self"); 361 baseStructure = stubInfo.u.getByIdSelf.baseObjectStructure.get(); 362 break; 363 case access_get_by_id_proto: 364 out.printf("proto"); 365 baseStructure = stubInfo.u.getByIdProto.baseObjectStructure.get(); 366 prototypeStructure = stubInfo.u.getByIdProto.prototypeStructure.get(); 367 break; 368 case access_get_by_id_chain: 369 out.printf("chain"); 370 baseStructure = stubInfo.u.getByIdChain.baseObjectStructure.get(); 371 chain = stubInfo.u.getByIdChain.chain.get(); 372 break; 373 case access_get_by_id_self_list: 374 out.printf("self_list"); 375 structureList = stubInfo.u.getByIdSelfList.structureList; 376 listSize = stubInfo.u.getByIdSelfList.listSize; 377 break; 378 case access_get_by_id_proto_list: 379 out.printf("proto_list"); 380 structureList = stubInfo.u.getByIdProtoList.structureList; 381 listSize = stubInfo.u.getByIdProtoList.listSize; 382 break; 383 case access_unset: 384 out.printf("unset"); 385 break; 386 case access_get_by_id_generic: 387 out.printf("generic"); 388 break; 389 case access_get_array_length: 390 out.printf("array_length"); 391 break; 392 case access_get_string_length: 393 out.printf("string_length"); 394 break; 395 default: 396 RELEASE_ASSERT_NOT_REACHED(); 397 break; 398 } 399 400 if (baseStructure) { 401 out.printf(", "); 402 dumpStructure(out, "struct", exec, baseStructure, ident); 403 } 404 405 if (prototypeStructure) { 406 out.printf(", "); 407 dumpStructure(out, "prototypeStruct", exec, baseStructure, ident); 408 } 409 410 if (chain) { 411 out.printf(", "); 412 dumpChain(out, exec, chain, ident); 413 } 414 415 if (structureList) { 416 out.printf(", list = %p: [", structureList); 417 for (int i = 0; i < listSize; ++i) { 418 if (i) 419 out.printf(", "); 420 out.printf("("); 421 dumpStructure(out, "base", exec, structureList->list[i].base.get(), ident); 422 if (structureList->list[i].isChain) { 423 if (structureList->list[i].u.chain.get()) { 424 out.printf(", "); 425 dumpChain(out, exec, structureList->list[i].u.chain.get(), ident); 426 } 427 } else { 428 if (structureList->list[i].u.proto.get()) { 429 out.printf(", "); 430 dumpStructure(out, "proto", exec, structureList->list[i].u.proto.get(), ident); 431 } 432 } 433 out.printf(")"); 434 } 435 out.printf("]"); 436 } 437 out.printf(")"); 438 } 439 } 440#endif 441} 442 443void CodeBlock::printCallOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op, CacheDumpMode cacheDumpMode) 444{ 445 int func = (++it)->u.operand; 446 int argCount = (++it)->u.operand; 447 int registerOffset = (++it)->u.operand; 448 out.printf("[%4d] %s\t %s, %d, %d", location, op, registerName(exec, func).data(), argCount, registerOffset); 449 if (cacheDumpMode == DumpCaches) { 450#if ENABLE(LLINT) 451 LLIntCallLinkInfo* callLinkInfo = it[1].u.callLinkInfo; 452 if (callLinkInfo->lastSeenCallee) { 453 out.printf( 454 " llint(%p, exec %p)", 455 callLinkInfo->lastSeenCallee.get(), 456 callLinkInfo->lastSeenCallee->executable()); 457 } 458#endif 459#if ENABLE(JIT) 460 if (numberOfCallLinkInfos()) { 461 JSFunction* target = getCallLinkInfo(location).lastSeenCallee.get(); 462 if (target) 463 out.printf(" jit(%p, exec %p)", target, target->executable()); 464 } 465#endif 466 out.print(" status(", CallLinkStatus::computeFor(this, location), ")"); 467 } 468 it += 2; 469} 470 471void CodeBlock::printPutByIdOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op) 472{ 473 int r0 = (++it)->u.operand; 474 int id0 = (++it)->u.operand; 475 int r1 = (++it)->u.operand; 476 out.printf("[%4d] %s\t %s, %s, %s", location, op, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data()); 477 it += 5; 478} 479 480void CodeBlock::printStructure(PrintStream& out, const char* name, const Instruction* vPC, int operand) 481{ 482 unsigned instructionOffset = vPC - instructions().begin(); 483 out.printf(" [%4d] %s: %s\n", instructionOffset, name, pointerToSourceString(vPC[operand].u.structure).utf8().data()); 484} 485 486void CodeBlock::printStructures(PrintStream& out, const Instruction* vPC) 487{ 488 Interpreter* interpreter = m_vm->interpreter; 489 unsigned instructionOffset = vPC - instructions().begin(); 490 491 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id)) { 492 printStructure(out, "get_by_id", vPC, 4); 493 return; 494 } 495 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) { 496 printStructure(out, "get_by_id_self", vPC, 4); 497 return; 498 } 499 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) { 500 out.printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(vPC[4].u.structure).utf8().data(), pointerToSourceString(vPC[5].u.structure).utf8().data()); 501 return; 502 } 503 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) { 504 out.printf(" [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(vPC[4].u.structure).utf8().data(), pointerToSourceString(vPC[5].u.structure).utf8().data(), pointerToSourceString(vPC[6].u.structureChain).utf8().data()); 505 return; 506 } 507 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) { 508 out.printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(vPC[4].u.structure).utf8().data(), pointerToSourceString(vPC[5].u.structureChain).utf8().data()); 509 return; 510 } 511 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id)) { 512 printStructure(out, "put_by_id", vPC, 4); 513 return; 514 } 515 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) { 516 printStructure(out, "put_by_id_replace", vPC, 4); 517 return; 518 } 519 520 // These m_instructions doesn't ref Structures. 521 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)); 522} 523 524void CodeBlock::dumpBytecode(PrintStream& out) 525{ 526 // We only use the ExecState* for things that don't actually lead to JS execution, 527 // like converting a JSString to a String. Hence the globalExec is appropriate. 528 ExecState* exec = m_globalObject->globalExec(); 529 530 size_t instructionCount = 0; 531 532 for (size_t i = 0; i < instructions().size(); i += opcodeLengths[exec->interpreter()->getOpcodeID(instructions()[i].u.opcode)]) 533 ++instructionCount; 534 535 out.print(*this); 536 out.printf( 537 ": %lu m_instructions; %lu bytes; %d parameter(s); %d callee register(s); %d variable(s)", 538 static_cast<unsigned long>(instructions().size()), 539 static_cast<unsigned long>(instructions().size() * sizeof(Instruction)), 540 m_numParameters, m_numCalleeRegisters, m_numVars); 541 if (symbolTable() && symbolTable()->captureCount()) { 542 out.printf( 543 "; %d captured var(s) (from r%d to r%d, inclusive)", 544 symbolTable()->captureCount(), symbolTable()->captureStart(), symbolTable()->captureEnd() - 1); 545 } 546 if (usesArguments()) { 547 out.printf( 548 "; uses arguments, in r%d, r%d", 549 argumentsRegister(), 550 unmodifiedArgumentsRegister(argumentsRegister())); 551 } 552 if (needsFullScopeChain() && codeType() == FunctionCode) 553 out.printf("; activation in r%d", activationRegister()); 554 out.print("\n\nSource: ", sourceCodeOnOneLine(), "\n\n"); 555 556 const Instruction* begin = instructions().begin(); 557 const Instruction* end = instructions().end(); 558 for (const Instruction* it = begin; it != end; ++it) 559 dumpBytecode(out, exec, begin, it); 560 561 if (!m_identifiers.isEmpty()) { 562 out.printf("\nIdentifiers:\n"); 563 size_t i = 0; 564 do { 565 out.printf(" id%u = %s\n", static_cast<unsigned>(i), m_identifiers[i].string().utf8().data()); 566 ++i; 567 } while (i != m_identifiers.size()); 568 } 569 570 if (!m_constantRegisters.isEmpty()) { 571 out.printf("\nConstants:\n"); 572 size_t i = 0; 573 do { 574 out.printf(" k%u = %s\n", static_cast<unsigned>(i), valueToSourceString(exec, m_constantRegisters[i].get()).utf8().data()); 575 ++i; 576 } while (i < m_constantRegisters.size()); 577 } 578 579 if (size_t count = m_unlinkedCode->numberOfRegExps()) { 580 out.printf("\nm_regexps:\n"); 581 size_t i = 0; 582 do { 583 out.printf(" re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(m_unlinkedCode->regexp(i)).utf8().data()); 584 ++i; 585 } while (i < count); 586 } 587 588#if ENABLE(JIT) 589 if (!m_structureStubInfos.isEmpty()) 590 out.printf("\nStructures:\n"); 591#endif 592 593 if (m_rareData && !m_rareData->m_exceptionHandlers.isEmpty()) { 594 out.printf("\nException Handlers:\n"); 595 unsigned i = 0; 596 do { 597 out.printf("\t %d: { start: [%4d] end: [%4d] target: [%4d] depth: [%4d] }\n", i + 1, m_rareData->m_exceptionHandlers[i].start, m_rareData->m_exceptionHandlers[i].end, m_rareData->m_exceptionHandlers[i].target, m_rareData->m_exceptionHandlers[i].scopeDepth); 598 ++i; 599 } while (i < m_rareData->m_exceptionHandlers.size()); 600 } 601 602 if (m_rareData && !m_rareData->m_immediateSwitchJumpTables.isEmpty()) { 603 out.printf("Immediate Switch Jump Tables:\n"); 604 unsigned i = 0; 605 do { 606 out.printf(" %1d = {\n", i); 607 int entry = 0; 608 Vector<int32_t>::const_iterator end = m_rareData->m_immediateSwitchJumpTables[i].branchOffsets.end(); 609 for (Vector<int32_t>::const_iterator iter = m_rareData->m_immediateSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) { 610 if (!*iter) 611 continue; 612 out.printf("\t\t%4d => %04d\n", entry + m_rareData->m_immediateSwitchJumpTables[i].min, *iter); 613 } 614 out.printf(" }\n"); 615 ++i; 616 } while (i < m_rareData->m_immediateSwitchJumpTables.size()); 617 } 618 619 if (m_rareData && !m_rareData->m_characterSwitchJumpTables.isEmpty()) { 620 out.printf("\nCharacter Switch Jump Tables:\n"); 621 unsigned i = 0; 622 do { 623 out.printf(" %1d = {\n", i); 624 int entry = 0; 625 Vector<int32_t>::const_iterator end = m_rareData->m_characterSwitchJumpTables[i].branchOffsets.end(); 626 for (Vector<int32_t>::const_iterator iter = m_rareData->m_characterSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) { 627 if (!*iter) 628 continue; 629 ASSERT(!((i + m_rareData->m_characterSwitchJumpTables[i].min) & ~0xFFFF)); 630 UChar ch = static_cast<UChar>(entry + m_rareData->m_characterSwitchJumpTables[i].min); 631 out.printf("\t\t\"%s\" => %04d\n", String(&ch, 1).utf8().data(), *iter); 632 } 633 out.printf(" }\n"); 634 ++i; 635 } while (i < m_rareData->m_characterSwitchJumpTables.size()); 636 } 637 638 if (m_rareData && !m_rareData->m_stringSwitchJumpTables.isEmpty()) { 639 out.printf("\nString Switch Jump Tables:\n"); 640 unsigned i = 0; 641 do { 642 out.printf(" %1d = {\n", i); 643 StringJumpTable::StringOffsetTable::const_iterator end = m_rareData->m_stringSwitchJumpTables[i].offsetTable.end(); 644 for (StringJumpTable::StringOffsetTable::const_iterator iter = m_rareData->m_stringSwitchJumpTables[i].offsetTable.begin(); iter != end; ++iter) 645 out.printf("\t\t\"%s\" => %04d\n", String(iter->key).utf8().data(), iter->value.branchOffset); 646 out.printf(" }\n"); 647 ++i; 648 } while (i < m_rareData->m_stringSwitchJumpTables.size()); 649 } 650 651 out.printf("\n"); 652} 653 654void CodeBlock::beginDumpProfiling(PrintStream& out, bool& hasPrintedProfiling) 655{ 656 if (hasPrintedProfiling) { 657 out.print("; "); 658 return; 659 } 660 661 out.print(" "); 662 hasPrintedProfiling = true; 663} 664 665void CodeBlock::dumpValueProfiling(PrintStream& out, const Instruction*& it, bool& hasPrintedProfiling) 666{ 667 ++it; 668#if ENABLE(VALUE_PROFILER) 669 CString description = it->u.profile->briefDescription(); 670 if (!description.length()) 671 return; 672 beginDumpProfiling(out, hasPrintedProfiling); 673 out.print(description); 674#else 675 UNUSED_PARAM(out); 676 UNUSED_PARAM(hasPrintedProfiling); 677#endif 678} 679 680void CodeBlock::dumpArrayProfiling(PrintStream& out, const Instruction*& it, bool& hasPrintedProfiling) 681{ 682 ++it; 683#if ENABLE(VALUE_PROFILER) 684 CString description = it->u.arrayProfile->briefDescription(this); 685 if (!description.length()) 686 return; 687 beginDumpProfiling(out, hasPrintedProfiling); 688 out.print(description); 689#else 690 UNUSED_PARAM(out); 691 UNUSED_PARAM(hasPrintedProfiling); 692#endif 693} 694 695#if ENABLE(VALUE_PROFILER) 696void CodeBlock::dumpRareCaseProfile(PrintStream& out, const char* name, RareCaseProfile* profile, bool& hasPrintedProfiling) 697{ 698 if (!profile || !profile->m_counter) 699 return; 700 701 beginDumpProfiling(out, hasPrintedProfiling); 702 out.print(name, profile->m_counter); 703} 704#endif 705 706void CodeBlock::dumpBytecode(PrintStream& out, ExecState* exec, const Instruction* begin, const Instruction*& it) 707{ 708 int location = it - begin; 709 bool hasPrintedProfiling = false; 710 switch (exec->interpreter()->getOpcodeID(it->u.opcode)) { 711 case op_enter: { 712 out.printf("[%4d] enter", location); 713 break; 714 } 715 case op_create_activation: { 716 int r0 = (++it)->u.operand; 717 out.printf("[%4d] create_activation %s", location, registerName(exec, r0).data()); 718 break; 719 } 720 case op_create_arguments: { 721 int r0 = (++it)->u.operand; 722 out.printf("[%4d] create_arguments\t %s", location, registerName(exec, r0).data()); 723 break; 724 } 725 case op_init_lazy_reg: { 726 int r0 = (++it)->u.operand; 727 out.printf("[%4d] init_lazy_reg\t %s", location, registerName(exec, r0).data()); 728 break; 729 } 730 case op_get_callee: { 731 int r0 = (++it)->u.operand; 732 out.printf("[%4d] op_get_callee %s\n", location, registerName(exec, r0).data()); 733 ++it; 734 break; 735 } 736 case op_create_this: { 737 int r0 = (++it)->u.operand; 738 int r1 = (++it)->u.operand; 739 unsigned inferredInlineCapacity = (++it)->u.operand; 740 out.printf("[%4d] create_this %s, %s, %u", location, registerName(exec, r0).data(), registerName(exec, r1).data(), inferredInlineCapacity); 741 break; 742 } 743 case op_convert_this: { 744 int r0 = (++it)->u.operand; 745 out.printf("[%4d] convert_this\t %s", location, registerName(exec, r0).data()); 746 ++it; // Skip value profile. 747 break; 748 } 749 case op_new_object: { 750 int r0 = (++it)->u.operand; 751 unsigned inferredInlineCapacity = (++it)->u.operand; 752 out.printf("[%4d] new_object\t %s, %u", location, registerName(exec, r0).data(), inferredInlineCapacity); 753 ++it; // Skip object allocation profile. 754 break; 755 } 756 case op_new_array: { 757 int dst = (++it)->u.operand; 758 int argv = (++it)->u.operand; 759 int argc = (++it)->u.operand; 760 out.printf("[%4d] new_array\t %s, %s, %d", location, registerName(exec, dst).data(), registerName(exec, argv).data(), argc); 761 ++it; // Skip array allocation profile. 762 break; 763 } 764 case op_new_array_with_size: { 765 int dst = (++it)->u.operand; 766 int length = (++it)->u.operand; 767 out.printf("[%4d] new_array_with_size\t %s, %s", location, registerName(exec, dst).data(), registerName(exec, length).data()); 768 ++it; // Skip array allocation profile. 769 break; 770 } 771 case op_new_array_buffer: { 772 int dst = (++it)->u.operand; 773 int argv = (++it)->u.operand; 774 int argc = (++it)->u.operand; 775 out.printf("[%4d] new_array_buffer\t %s, %d, %d", location, registerName(exec, dst).data(), argv, argc); 776 ++it; // Skip array allocation profile. 777 break; 778 } 779 case op_new_regexp: { 780 int r0 = (++it)->u.operand; 781 int re0 = (++it)->u.operand; 782 out.printf("[%4d] new_regexp\t %s, ", location, registerName(exec, r0).data()); 783 if (r0 >=0 && r0 < (int)m_unlinkedCode->numberOfRegExps()) 784 out.printf("%s", regexpName(re0, regexp(re0)).data()); 785 else 786 out.printf("bad_regexp(%d)", re0); 787 break; 788 } 789 case op_mov: { 790 int r0 = (++it)->u.operand; 791 int r1 = (++it)->u.operand; 792 out.printf("[%4d] mov\t\t %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data()); 793 break; 794 } 795 case op_not: { 796 printUnaryOp(out, exec, location, it, "not"); 797 break; 798 } 799 case op_eq: { 800 printBinaryOp(out, exec, location, it, "eq"); 801 break; 802 } 803 case op_eq_null: { 804 printUnaryOp(out, exec, location, it, "eq_null"); 805 break; 806 } 807 case op_neq: { 808 printBinaryOp(out, exec, location, it, "neq"); 809 break; 810 } 811 case op_neq_null: { 812 printUnaryOp(out, exec, location, it, "neq_null"); 813 break; 814 } 815 case op_stricteq: { 816 printBinaryOp(out, exec, location, it, "stricteq"); 817 break; 818 } 819 case op_nstricteq: { 820 printBinaryOp(out, exec, location, it, "nstricteq"); 821 break; 822 } 823 case op_less: { 824 printBinaryOp(out, exec, location, it, "less"); 825 break; 826 } 827 case op_lesseq: { 828 printBinaryOp(out, exec, location, it, "lesseq"); 829 break; 830 } 831 case op_greater: { 832 printBinaryOp(out, exec, location, it, "greater"); 833 break; 834 } 835 case op_greatereq: { 836 printBinaryOp(out, exec, location, it, "greatereq"); 837 break; 838 } 839 case op_inc: { 840 int r0 = (++it)->u.operand; 841 out.printf("[%4d] pre_inc\t\t %s", location, registerName(exec, r0).data()); 842 break; 843 } 844 case op_dec: { 845 int r0 = (++it)->u.operand; 846 out.printf("[%4d] pre_dec\t\t %s", location, registerName(exec, r0).data()); 847 break; 848 } 849 case op_to_number: { 850 printUnaryOp(out, exec, location, it, "to_number"); 851 break; 852 } 853 case op_negate: { 854 printUnaryOp(out, exec, location, it, "negate"); 855 break; 856 } 857 case op_add: { 858 printBinaryOp(out, exec, location, it, "add"); 859 ++it; 860 break; 861 } 862 case op_mul: { 863 printBinaryOp(out, exec, location, it, "mul"); 864 ++it; 865 break; 866 } 867 case op_div: { 868 printBinaryOp(out, exec, location, it, "div"); 869 ++it; 870 break; 871 } 872 case op_mod: { 873 printBinaryOp(out, exec, location, it, "mod"); 874 break; 875 } 876 case op_sub: { 877 printBinaryOp(out, exec, location, it, "sub"); 878 ++it; 879 break; 880 } 881 case op_lshift: { 882 printBinaryOp(out, exec, location, it, "lshift"); 883 break; 884 } 885 case op_rshift: { 886 printBinaryOp(out, exec, location, it, "rshift"); 887 break; 888 } 889 case op_urshift: { 890 printBinaryOp(out, exec, location, it, "urshift"); 891 break; 892 } 893 case op_bitand: { 894 printBinaryOp(out, exec, location, it, "bitand"); 895 ++it; 896 break; 897 } 898 case op_bitxor: { 899 printBinaryOp(out, exec, location, it, "bitxor"); 900 ++it; 901 break; 902 } 903 case op_bitor: { 904 printBinaryOp(out, exec, location, it, "bitor"); 905 ++it; 906 break; 907 } 908 case op_check_has_instance: { 909 int r0 = (++it)->u.operand; 910 int r1 = (++it)->u.operand; 911 int r2 = (++it)->u.operand; 912 int offset = (++it)->u.operand; 913 out.printf("[%4d] check_has_instance\t\t %s, %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), offset, location + offset); 914 break; 915 } 916 case op_instanceof: { 917 int r0 = (++it)->u.operand; 918 int r1 = (++it)->u.operand; 919 int r2 = (++it)->u.operand; 920 out.printf("[%4d] instanceof\t\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); 921 break; 922 } 923 case op_typeof: { 924 printUnaryOp(out, exec, location, it, "typeof"); 925 break; 926 } 927 case op_is_undefined: { 928 printUnaryOp(out, exec, location, it, "is_undefined"); 929 break; 930 } 931 case op_is_boolean: { 932 printUnaryOp(out, exec, location, it, "is_boolean"); 933 break; 934 } 935 case op_is_number: { 936 printUnaryOp(out, exec, location, it, "is_number"); 937 break; 938 } 939 case op_is_string: { 940 printUnaryOp(out, exec, location, it, "is_string"); 941 break; 942 } 943 case op_is_object: { 944 printUnaryOp(out, exec, location, it, "is_object"); 945 break; 946 } 947 case op_is_function: { 948 printUnaryOp(out, exec, location, it, "is_function"); 949 break; 950 } 951 case op_in: { 952 printBinaryOp(out, exec, location, it, "in"); 953 break; 954 } 955 case op_put_to_base_variable: 956 case op_put_to_base: { 957 int base = (++it)->u.operand; 958 int id0 = (++it)->u.operand; 959 int value = (++it)->u.operand; 960 int resolveInfo = (++it)->u.operand; 961 out.printf("[%4d] put_to_base\t %s, %s, %s, %d", location, registerName(exec, base).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, value).data(), resolveInfo); 962 break; 963 } 964 case op_resolve: 965 case op_resolve_global_property: 966 case op_resolve_global_var: 967 case op_resolve_scoped_var: 968 case op_resolve_scoped_var_on_top_scope: 969 case op_resolve_scoped_var_with_top_scope_check: { 970 int r0 = (++it)->u.operand; 971 int id0 = (++it)->u.operand; 972 int resolveInfo = (++it)->u.operand; 973 out.printf("[%4d] resolve\t\t %s, %s, %d", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), resolveInfo); 974 dumpValueProfiling(out, it, hasPrintedProfiling); 975 break; 976 } 977 case op_get_scoped_var: { 978 int r0 = (++it)->u.operand; 979 int index = (++it)->u.operand; 980 int skipLevels = (++it)->u.operand; 981 out.printf("[%4d] get_scoped_var\t %s, %d, %d", location, registerName(exec, r0).data(), index, skipLevels); 982 dumpValueProfiling(out, it, hasPrintedProfiling); 983 break; 984 } 985 case op_put_scoped_var: { 986 int index = (++it)->u.operand; 987 int skipLevels = (++it)->u.operand; 988 int r0 = (++it)->u.operand; 989 out.printf("[%4d] put_scoped_var\t %d, %d, %s", location, index, skipLevels, registerName(exec, r0).data()); 990 break; 991 } 992 case op_init_global_const_nop: { 993 out.printf("[%4d] init_global_const_nop\t", location); 994 it++; 995 it++; 996 it++; 997 it++; 998 break; 999 } 1000 case op_init_global_const: { 1001 WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer; 1002 int r0 = (++it)->u.operand; 1003 out.printf("[%4d] init_global_const\t g%d(%p), %s", location, m_globalObject->findRegisterIndex(registerPointer), registerPointer, registerName(exec, r0).data()); 1004 it++; 1005 it++; 1006 break; 1007 } 1008 case op_init_global_const_check: { 1009 WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer; 1010 int r0 = (++it)->u.operand; 1011 out.printf("[%4d] init_global_const_check\t g%d(%p), %s", location, m_globalObject->findRegisterIndex(registerPointer), registerPointer, registerName(exec, r0).data()); 1012 it++; 1013 it++; 1014 break; 1015 } 1016 case op_resolve_base_to_global: 1017 case op_resolve_base_to_global_dynamic: 1018 case op_resolve_base_to_scope: 1019 case op_resolve_base_to_scope_with_top_scope_check: 1020 case op_resolve_base: { 1021 int r0 = (++it)->u.operand; 1022 int id0 = (++it)->u.operand; 1023 int isStrict = (++it)->u.operand; 1024 int resolveInfo = (++it)->u.operand; 1025 int putToBaseInfo = (++it)->u.operand; 1026 out.printf("[%4d] resolve_base%s\t %s, %s, %d, %d", location, isStrict ? "_strict" : "", registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), resolveInfo, putToBaseInfo); 1027 dumpValueProfiling(out, it, hasPrintedProfiling); 1028 break; 1029 } 1030 case op_resolve_with_base: { 1031 int r0 = (++it)->u.operand; 1032 int r1 = (++it)->u.operand; 1033 int id0 = (++it)->u.operand; 1034 int resolveInfo = (++it)->u.operand; 1035 int putToBaseInfo = (++it)->u.operand; 1036 out.printf("[%4d] resolve_with_base %s, %s, %s, %d, %d", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data(), resolveInfo, putToBaseInfo); 1037 dumpValueProfiling(out, it, hasPrintedProfiling); 1038 break; 1039 } 1040 case op_resolve_with_this: { 1041 int r0 = (++it)->u.operand; 1042 int r1 = (++it)->u.operand; 1043 int id0 = (++it)->u.operand; 1044 int resolveInfo = (++it)->u.operand; 1045 out.printf("[%4d] resolve_with_this %s, %s, %s, %d", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data(), resolveInfo); 1046 dumpValueProfiling(out, it, hasPrintedProfiling); 1047 break; 1048 } 1049 case op_get_by_id: 1050 case op_get_by_id_out_of_line: 1051 case op_get_by_id_self: 1052 case op_get_by_id_proto: 1053 case op_get_by_id_chain: 1054 case op_get_by_id_getter_self: 1055 case op_get_by_id_getter_proto: 1056 case op_get_by_id_getter_chain: 1057 case op_get_by_id_custom_self: 1058 case op_get_by_id_custom_proto: 1059 case op_get_by_id_custom_chain: 1060 case op_get_by_id_generic: 1061 case op_get_array_length: 1062 case op_get_string_length: { 1063 printGetByIdOp(out, exec, location, it); 1064 printGetByIdCacheStatus(out, exec, location); 1065 dumpValueProfiling(out, it, hasPrintedProfiling); 1066 break; 1067 } 1068 case op_get_arguments_length: { 1069 printUnaryOp(out, exec, location, it, "get_arguments_length"); 1070 it++; 1071 break; 1072 } 1073 case op_put_by_id: { 1074 printPutByIdOp(out, exec, location, it, "put_by_id"); 1075 break; 1076 } 1077 case op_put_by_id_out_of_line: { 1078 printPutByIdOp(out, exec, location, it, "put_by_id_out_of_line"); 1079 break; 1080 } 1081 case op_put_by_id_replace: { 1082 printPutByIdOp(out, exec, location, it, "put_by_id_replace"); 1083 break; 1084 } 1085 case op_put_by_id_transition: { 1086 printPutByIdOp(out, exec, location, it, "put_by_id_transition"); 1087 break; 1088 } 1089 case op_put_by_id_transition_direct: { 1090 printPutByIdOp(out, exec, location, it, "put_by_id_transition_direct"); 1091 break; 1092 } 1093 case op_put_by_id_transition_direct_out_of_line: { 1094 printPutByIdOp(out, exec, location, it, "put_by_id_transition_direct_out_of_line"); 1095 break; 1096 } 1097 case op_put_by_id_transition_normal: { 1098 printPutByIdOp(out, exec, location, it, "put_by_id_transition_normal"); 1099 break; 1100 } 1101 case op_put_by_id_transition_normal_out_of_line: { 1102 printPutByIdOp(out, exec, location, it, "put_by_id_transition_normal_out_of_line"); 1103 break; 1104 } 1105 case op_put_by_id_generic: { 1106 printPutByIdOp(out, exec, location, it, "put_by_id_generic"); 1107 break; 1108 } 1109 case op_put_getter_setter: { 1110 int r0 = (++it)->u.operand; 1111 int id0 = (++it)->u.operand; 1112 int r1 = (++it)->u.operand; 1113 int r2 = (++it)->u.operand; 1114 out.printf("[%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()); 1115 break; 1116 } 1117 case op_del_by_id: { 1118 int r0 = (++it)->u.operand; 1119 int r1 = (++it)->u.operand; 1120 int id0 = (++it)->u.operand; 1121 out.printf("[%4d] del_by_id\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data()); 1122 break; 1123 } 1124 case op_get_by_val: { 1125 int r0 = (++it)->u.operand; 1126 int r1 = (++it)->u.operand; 1127 int r2 = (++it)->u.operand; 1128 out.printf("[%4d] get_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); 1129 dumpArrayProfiling(out, it, hasPrintedProfiling); 1130 dumpValueProfiling(out, it, hasPrintedProfiling); 1131 break; 1132 } 1133 case op_get_argument_by_val: { 1134 int r0 = (++it)->u.operand; 1135 int r1 = (++it)->u.operand; 1136 int r2 = (++it)->u.operand; 1137 out.printf("[%4d] get_argument_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); 1138 ++it; 1139 dumpValueProfiling(out, it, hasPrintedProfiling); 1140 break; 1141 } 1142 case op_get_by_pname: { 1143 int r0 = (++it)->u.operand; 1144 int r1 = (++it)->u.operand; 1145 int r2 = (++it)->u.operand; 1146 int r3 = (++it)->u.operand; 1147 int r4 = (++it)->u.operand; 1148 int r5 = (++it)->u.operand; 1149 out.printf("[%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()); 1150 break; 1151 } 1152 case op_put_by_val: { 1153 int r0 = (++it)->u.operand; 1154 int r1 = (++it)->u.operand; 1155 int r2 = (++it)->u.operand; 1156 out.printf("[%4d] put_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); 1157 dumpArrayProfiling(out, it, hasPrintedProfiling); 1158 break; 1159 } 1160 case op_del_by_val: { 1161 int r0 = (++it)->u.operand; 1162 int r1 = (++it)->u.operand; 1163 int r2 = (++it)->u.operand; 1164 out.printf("[%4d] del_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); 1165 break; 1166 } 1167 case op_put_by_index: { 1168 int r0 = (++it)->u.operand; 1169 unsigned n0 = (++it)->u.operand; 1170 int r1 = (++it)->u.operand; 1171 out.printf("[%4d] put_by_index\t %s, %u, %s", location, registerName(exec, r0).data(), n0, registerName(exec, r1).data()); 1172 break; 1173 } 1174 case op_jmp: { 1175 int offset = (++it)->u.operand; 1176 out.printf("[%4d] jmp\t\t %d(->%d)", location, offset, location + offset); 1177 break; 1178 } 1179 case op_jtrue: { 1180 printConditionalJump(out, exec, begin, it, location, "jtrue"); 1181 break; 1182 } 1183 case op_jfalse: { 1184 printConditionalJump(out, exec, begin, it, location, "jfalse"); 1185 break; 1186 } 1187 case op_jeq_null: { 1188 printConditionalJump(out, exec, begin, it, location, "jeq_null"); 1189 break; 1190 } 1191 case op_jneq_null: { 1192 printConditionalJump(out, exec, begin, it, location, "jneq_null"); 1193 break; 1194 } 1195 case op_jneq_ptr: { 1196 int r0 = (++it)->u.operand; 1197 Special::Pointer pointer = (++it)->u.specialPointer; 1198 int offset = (++it)->u.operand; 1199 out.printf("[%4d] jneq_ptr\t\t %s, %d (%p), %d(->%d)", location, registerName(exec, r0).data(), pointer, m_globalObject->actualPointerFor(pointer), offset, location + offset); 1200 break; 1201 } 1202 case op_jless: { 1203 int r0 = (++it)->u.operand; 1204 int r1 = (++it)->u.operand; 1205 int offset = (++it)->u.operand; 1206 out.printf("[%4d] jless\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); 1207 break; 1208 } 1209 case op_jlesseq: { 1210 int r0 = (++it)->u.operand; 1211 int r1 = (++it)->u.operand; 1212 int offset = (++it)->u.operand; 1213 out.printf("[%4d] jlesseq\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); 1214 break; 1215 } 1216 case op_jgreater: { 1217 int r0 = (++it)->u.operand; 1218 int r1 = (++it)->u.operand; 1219 int offset = (++it)->u.operand; 1220 out.printf("[%4d] jgreater\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); 1221 break; 1222 } 1223 case op_jgreatereq: { 1224 int r0 = (++it)->u.operand; 1225 int r1 = (++it)->u.operand; 1226 int offset = (++it)->u.operand; 1227 out.printf("[%4d] jgreatereq\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); 1228 break; 1229 } 1230 case op_jnless: { 1231 int r0 = (++it)->u.operand; 1232 int r1 = (++it)->u.operand; 1233 int offset = (++it)->u.operand; 1234 out.printf("[%4d] jnless\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); 1235 break; 1236 } 1237 case op_jnlesseq: { 1238 int r0 = (++it)->u.operand; 1239 int r1 = (++it)->u.operand; 1240 int offset = (++it)->u.operand; 1241 out.printf("[%4d] jnlesseq\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); 1242 break; 1243 } 1244 case op_jngreater: { 1245 int r0 = (++it)->u.operand; 1246 int r1 = (++it)->u.operand; 1247 int offset = (++it)->u.operand; 1248 out.printf("[%4d] jngreater\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); 1249 break; 1250 } 1251 case op_jngreatereq: { 1252 int r0 = (++it)->u.operand; 1253 int r1 = (++it)->u.operand; 1254 int offset = (++it)->u.operand; 1255 out.printf("[%4d] jngreatereq\t\t %s, %s, %d(->%d)", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset); 1256 break; 1257 } 1258 case op_loop_hint: { 1259 out.printf("[%4d] loop_hint", location); 1260 break; 1261 } 1262 case op_switch_imm: { 1263 int tableIndex = (++it)->u.operand; 1264 int defaultTarget = (++it)->u.operand; 1265 int scrutineeRegister = (++it)->u.operand; 1266 out.printf("[%4d] switch_imm\t %d, %d(->%d), %s", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data()); 1267 break; 1268 } 1269 case op_switch_char: { 1270 int tableIndex = (++it)->u.operand; 1271 int defaultTarget = (++it)->u.operand; 1272 int scrutineeRegister = (++it)->u.operand; 1273 out.printf("[%4d] switch_char\t %d, %d(->%d), %s", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data()); 1274 break; 1275 } 1276 case op_switch_string: { 1277 int tableIndex = (++it)->u.operand; 1278 int defaultTarget = (++it)->u.operand; 1279 int scrutineeRegister = (++it)->u.operand; 1280 out.printf("[%4d] switch_string\t %d, %d(->%d), %s", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data()); 1281 break; 1282 } 1283 case op_new_func: { 1284 int r0 = (++it)->u.operand; 1285 int f0 = (++it)->u.operand; 1286 int shouldCheck = (++it)->u.operand; 1287 out.printf("[%4d] new_func\t\t %s, f%d, %s", location, registerName(exec, r0).data(), f0, shouldCheck ? "<Checked>" : "<Unchecked>"); 1288 break; 1289 } 1290 case op_new_func_exp: { 1291 int r0 = (++it)->u.operand; 1292 int f0 = (++it)->u.operand; 1293 out.printf("[%4d] new_func_exp\t %s, f%d", location, registerName(exec, r0).data(), f0); 1294 break; 1295 } 1296 case op_call: { 1297 printCallOp(out, exec, location, it, "call", DumpCaches); 1298 break; 1299 } 1300 case op_call_eval: { 1301 printCallOp(out, exec, location, it, "call_eval", DontDumpCaches); 1302 break; 1303 } 1304 case op_call_varargs: { 1305 int callee = (++it)->u.operand; 1306 int thisValue = (++it)->u.operand; 1307 int arguments = (++it)->u.operand; 1308 int firstFreeRegister = (++it)->u.operand; 1309 out.printf("[%4d] call_varargs\t %s, %s, %s, %d", location, registerName(exec, callee).data(), registerName(exec, thisValue).data(), registerName(exec, arguments).data(), firstFreeRegister); 1310 break; 1311 } 1312 case op_tear_off_activation: { 1313 int r0 = (++it)->u.operand; 1314 out.printf("[%4d] tear_off_activation\t %s", location, registerName(exec, r0).data()); 1315 break; 1316 } 1317 case op_tear_off_arguments: { 1318 int r0 = (++it)->u.operand; 1319 int r1 = (++it)->u.operand; 1320 out.printf("[%4d] tear_off_arguments %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data()); 1321 break; 1322 } 1323 case op_ret: { 1324 int r0 = (++it)->u.operand; 1325 out.printf("[%4d] ret\t\t %s", location, registerName(exec, r0).data()); 1326 break; 1327 } 1328 case op_call_put_result: { 1329 int r0 = (++it)->u.operand; 1330 out.printf("[%4d] call_put_result\t\t %s", location, registerName(exec, r0).data()); 1331 dumpValueProfiling(out, it, hasPrintedProfiling); 1332 break; 1333 } 1334 case op_ret_object_or_this: { 1335 int r0 = (++it)->u.operand; 1336 int r1 = (++it)->u.operand; 1337 out.printf("[%4d] constructor_ret\t\t %s %s", location, registerName(exec, r0).data(), registerName(exec, r1).data()); 1338 break; 1339 } 1340 case op_construct: { 1341 printCallOp(out, exec, location, it, "construct", DumpCaches); 1342 break; 1343 } 1344 case op_strcat: { 1345 int r0 = (++it)->u.operand; 1346 int r1 = (++it)->u.operand; 1347 int count = (++it)->u.operand; 1348 out.printf("[%4d] strcat\t\t %s, %s, %d", location, registerName(exec, r0).data(), registerName(exec, r1).data(), count); 1349 break; 1350 } 1351 case op_to_primitive: { 1352 int r0 = (++it)->u.operand; 1353 int r1 = (++it)->u.operand; 1354 out.printf("[%4d] to_primitive\t %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data()); 1355 break; 1356 } 1357 case op_get_pnames: { 1358 int r0 = it[1].u.operand; 1359 int r1 = it[2].u.operand; 1360 int r2 = it[3].u.operand; 1361 int r3 = it[4].u.operand; 1362 int offset = it[5].u.operand; 1363 out.printf("[%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); 1364 it += OPCODE_LENGTH(op_get_pnames) - 1; 1365 break; 1366 } 1367 case op_next_pname: { 1368 int dest = it[1].u.operand; 1369 int base = it[2].u.operand; 1370 int i = it[3].u.operand; 1371 int size = it[4].u.operand; 1372 int iter = it[5].u.operand; 1373 int offset = it[6].u.operand; 1374 out.printf("[%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); 1375 it += OPCODE_LENGTH(op_next_pname) - 1; 1376 break; 1377 } 1378 case op_push_with_scope: { 1379 int r0 = (++it)->u.operand; 1380 out.printf("[%4d] push_with_scope\t %s", location, registerName(exec, r0).data()); 1381 break; 1382 } 1383 case op_pop_scope: { 1384 out.printf("[%4d] pop_scope", location); 1385 break; 1386 } 1387 case op_push_name_scope: { 1388 int id0 = (++it)->u.operand; 1389 int r1 = (++it)->u.operand; 1390 unsigned attributes = (++it)->u.operand; 1391 out.printf("[%4d] push_name_scope \t%s, %s, %u", location, idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data(), attributes); 1392 break; 1393 } 1394 case op_catch: { 1395 int r0 = (++it)->u.operand; 1396 out.printf("[%4d] catch\t\t %s", location, registerName(exec, r0).data()); 1397 break; 1398 } 1399 case op_throw: { 1400 int r0 = (++it)->u.operand; 1401 out.printf("[%4d] throw\t\t %s", location, registerName(exec, r0).data()); 1402 break; 1403 } 1404 case op_throw_static_error: { 1405 int k0 = (++it)->u.operand; 1406 int k1 = (++it)->u.operand; 1407 out.printf("[%4d] throw_static_error\t %s, %s", location, constantName(exec, k0, getConstant(k0)).data(), k1 ? "true" : "false"); 1408 break; 1409 } 1410 case op_debug: { 1411 int debugHookID = (++it)->u.operand; 1412 int firstLine = (++it)->u.operand; 1413 int lastLine = (++it)->u.operand; 1414 int column = (++it)->u.operand; 1415 out.printf("[%4d] debug\t\t %s, %d, %d, %d", location, debugHookName(debugHookID), firstLine, lastLine, column); 1416 break; 1417 } 1418 case op_profile_will_call: { 1419 int function = (++it)->u.operand; 1420 out.printf("[%4d] profile_will_call %s", location, registerName(exec, function).data()); 1421 break; 1422 } 1423 case op_profile_did_call: { 1424 int function = (++it)->u.operand; 1425 out.printf("[%4d] profile_did_call\t %s", location, registerName(exec, function).data()); 1426 break; 1427 } 1428 case op_end: { 1429 int r0 = (++it)->u.operand; 1430 out.printf("[%4d] end\t\t %s", location, registerName(exec, r0).data()); 1431 break; 1432 } 1433#if ENABLE(LLINT_C_LOOP) 1434 default: 1435 RELEASE_ASSERT_NOT_REACHED(); 1436#endif 1437 } 1438 1439#if ENABLE(VALUE_PROFILER) 1440 dumpRareCaseProfile(out, "rare case: ", rareCaseProfileForBytecodeOffset(location), hasPrintedProfiling); 1441 dumpRareCaseProfile(out, "special fast case: ", specialFastCaseProfileForBytecodeOffset(location), hasPrintedProfiling); 1442#endif 1443 1444#if ENABLE(DFG_JIT) 1445 Vector<FrequentExitSite> exitSites = exitProfile().exitSitesFor(location); 1446 if (!exitSites.isEmpty()) { 1447 out.print(" !! frequent exits: "); 1448 CommaPrinter comma; 1449 for (unsigned i = 0; i < exitSites.size(); ++i) 1450 out.print(comma, exitSites[i].kind()); 1451 } 1452#else // ENABLE(DFG_JIT) 1453 UNUSED_PARAM(location); 1454#endif // ENABLE(DFG_JIT) 1455 out.print("\n"); 1456} 1457 1458void CodeBlock::dumpBytecode(PrintStream& out, unsigned bytecodeOffset) 1459{ 1460 ExecState* exec = m_globalObject->globalExec(); 1461 const Instruction* it = instructions().begin() + bytecodeOffset; 1462 dumpBytecode(out, exec, instructions().begin(), it); 1463} 1464 1465#if DUMP_CODE_BLOCK_STATISTICS 1466static HashSet<CodeBlock*> liveCodeBlockSet; 1467#endif 1468 1469#define FOR_EACH_MEMBER_VECTOR(macro) \ 1470 macro(instructions) \ 1471 macro(globalResolveInfos) \ 1472 macro(structureStubInfos) \ 1473 macro(callLinkInfos) \ 1474 macro(linkedCallerList) \ 1475 macro(identifiers) \ 1476 macro(functionExpressions) \ 1477 macro(constantRegisters) 1478 1479#define FOR_EACH_MEMBER_VECTOR_RARE_DATA(macro) \ 1480 macro(regexps) \ 1481 macro(functions) \ 1482 macro(exceptionHandlers) \ 1483 macro(immediateSwitchJumpTables) \ 1484 macro(characterSwitchJumpTables) \ 1485 macro(stringSwitchJumpTables) \ 1486 macro(evalCodeCache) \ 1487 macro(expressionInfo) \ 1488 macro(lineInfo) \ 1489 macro(callReturnIndexVector) 1490 1491template<typename T> 1492static size_t sizeInBytes(const Vector<T>& vector) 1493{ 1494 return vector.capacity() * sizeof(T); 1495} 1496 1497void CodeBlock::dumpStatistics() 1498{ 1499#if DUMP_CODE_BLOCK_STATISTICS 1500 #define DEFINE_VARS(name) size_t name##IsNotEmpty = 0; size_t name##TotalSize = 0; 1501 FOR_EACH_MEMBER_VECTOR(DEFINE_VARS) 1502 FOR_EACH_MEMBER_VECTOR_RARE_DATA(DEFINE_VARS) 1503 #undef DEFINE_VARS 1504 1505 // Non-vector data members 1506 size_t evalCodeCacheIsNotEmpty = 0; 1507 1508 size_t symbolTableIsNotEmpty = 0; 1509 size_t symbolTableTotalSize = 0; 1510 1511 size_t hasRareData = 0; 1512 1513 size_t isFunctionCode = 0; 1514 size_t isGlobalCode = 0; 1515 size_t isEvalCode = 0; 1516 1517 HashSet<CodeBlock*>::const_iterator end = liveCodeBlockSet.end(); 1518 for (HashSet<CodeBlock*>::const_iterator it = liveCodeBlockSet.begin(); it != end; ++it) { 1519 CodeBlock* codeBlock = *it; 1520 1521 #define GET_STATS(name) if (!codeBlock->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_##name); } 1522 FOR_EACH_MEMBER_VECTOR(GET_STATS) 1523 #undef GET_STATS 1524 1525 if (codeBlock->symbolTable() && !codeBlock->symbolTable()->isEmpty()) { 1526 symbolTableIsNotEmpty++; 1527 symbolTableTotalSize += (codeBlock->symbolTable()->capacity() * (sizeof(SymbolTable::KeyType) + sizeof(SymbolTable::MappedType))); 1528 } 1529 1530 if (codeBlock->m_rareData) { 1531 hasRareData++; 1532 #define GET_STATS(name) if (!codeBlock->m_rareData->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_rareData->m_##name); } 1533 FOR_EACH_MEMBER_VECTOR_RARE_DATA(GET_STATS) 1534 #undef GET_STATS 1535 1536 if (!codeBlock->m_rareData->m_evalCodeCache.isEmpty()) 1537 evalCodeCacheIsNotEmpty++; 1538 } 1539 1540 switch (codeBlock->codeType()) { 1541 case FunctionCode: 1542 ++isFunctionCode; 1543 break; 1544 case GlobalCode: 1545 ++isGlobalCode; 1546 break; 1547 case EvalCode: 1548 ++isEvalCode; 1549 break; 1550 } 1551 } 1552 1553 size_t totalSize = 0; 1554 1555 #define GET_TOTAL_SIZE(name) totalSize += name##TotalSize; 1556 FOR_EACH_MEMBER_VECTOR(GET_TOTAL_SIZE) 1557 FOR_EACH_MEMBER_VECTOR_RARE_DATA(GET_TOTAL_SIZE) 1558 #undef GET_TOTAL_SIZE 1559 1560 totalSize += symbolTableTotalSize; 1561 totalSize += (liveCodeBlockSet.size() * sizeof(CodeBlock)); 1562 1563 dataLogF("Number of live CodeBlocks: %d\n", liveCodeBlockSet.size()); 1564 dataLogF("Size of a single CodeBlock [sizeof(CodeBlock)]: %zu\n", sizeof(CodeBlock)); 1565 dataLogF("Size of all CodeBlocks: %zu\n", totalSize); 1566 dataLogF("Average size of a CodeBlock: %zu\n", totalSize / liveCodeBlockSet.size()); 1567 1568 dataLogF("Number of FunctionCode CodeBlocks: %zu (%.3f%%)\n", isFunctionCode, static_cast<double>(isFunctionCode) * 100.0 / liveCodeBlockSet.size()); 1569 dataLogF("Number of GlobalCode CodeBlocks: %zu (%.3f%%)\n", isGlobalCode, static_cast<double>(isGlobalCode) * 100.0 / liveCodeBlockSet.size()); 1570 dataLogF("Number of EvalCode CodeBlocks: %zu (%.3f%%)\n", isEvalCode, static_cast<double>(isEvalCode) * 100.0 / liveCodeBlockSet.size()); 1571 1572 dataLogF("Number of CodeBlocks with rare data: %zu (%.3f%%)\n", hasRareData, static_cast<double>(hasRareData) * 100.0 / liveCodeBlockSet.size()); 1573 1574 #define PRINT_STATS(name) dataLogF("Number of CodeBlocks with " #name ": %zu\n", name##IsNotEmpty); dataLogF("Size of all " #name ": %zu\n", name##TotalSize); 1575 FOR_EACH_MEMBER_VECTOR(PRINT_STATS) 1576 FOR_EACH_MEMBER_VECTOR_RARE_DATA(PRINT_STATS) 1577 #undef PRINT_STATS 1578 1579 dataLogF("Number of CodeBlocks with evalCodeCache: %zu\n", evalCodeCacheIsNotEmpty); 1580 dataLogF("Number of CodeBlocks with symbolTable: %zu\n", symbolTableIsNotEmpty); 1581 1582 dataLogF("Size of all symbolTables: %zu\n", symbolTableTotalSize); 1583 1584#else 1585 dataLogF("Dumping CodeBlock statistics is not enabled.\n"); 1586#endif 1587} 1588 1589CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other) 1590 : m_globalObject(other.m_globalObject) 1591 , m_heap(other.m_heap) 1592 , m_numCalleeRegisters(other.m_numCalleeRegisters) 1593 , m_numVars(other.m_numVars) 1594 , m_isConstructor(other.m_isConstructor) 1595 , m_unlinkedCode(*other.m_vm, other.m_ownerExecutable.get(), other.m_unlinkedCode.get()) 1596 , m_ownerExecutable(*other.m_vm, other.m_ownerExecutable.get(), other.m_ownerExecutable.get()) 1597 , m_vm(other.m_vm) 1598 , m_instructions(other.m_instructions) 1599 , m_thisRegister(other.m_thisRegister) 1600 , m_argumentsRegister(other.m_argumentsRegister) 1601 , m_activationRegister(other.m_activationRegister) 1602 , m_isStrictMode(other.m_isStrictMode) 1603 , m_needsActivation(other.m_needsActivation) 1604 , m_source(other.m_source) 1605 , m_sourceOffset(other.m_sourceOffset) 1606 , m_firstLineColumnOffset(other.m_firstLineColumnOffset) 1607 , m_codeType(other.m_codeType) 1608 , m_identifiers(other.m_identifiers) 1609 , m_constantRegisters(other.m_constantRegisters) 1610 , m_functionDecls(other.m_functionDecls) 1611 , m_functionExprs(other.m_functionExprs) 1612 , m_osrExitCounter(0) 1613 , m_optimizationDelayCounter(0) 1614 , m_reoptimizationRetryCounter(0) 1615 , m_resolveOperations(other.m_resolveOperations) 1616 , m_putToBaseOperations(other.m_putToBaseOperations) 1617#if ENABLE(JIT) 1618 , m_canCompileWithDFGState(DFG::CapabilityLevelNotSet) 1619#endif 1620{ 1621 setNumParameters(other.numParameters()); 1622 optimizeAfterWarmUp(); 1623 jitAfterWarmUp(); 1624 1625 if (other.m_rareData) { 1626 createRareDataIfNecessary(); 1627 1628 m_rareData->m_exceptionHandlers = other.m_rareData->m_exceptionHandlers; 1629 m_rareData->m_constantBuffers = other.m_rareData->m_constantBuffers; 1630 m_rareData->m_immediateSwitchJumpTables = other.m_rareData->m_immediateSwitchJumpTables; 1631 m_rareData->m_characterSwitchJumpTables = other.m_rareData->m_characterSwitchJumpTables; 1632 m_rareData->m_stringSwitchJumpTables = other.m_rareData->m_stringSwitchJumpTables; 1633 } 1634} 1635 1636CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock, JSGlobalObject* globalObject, unsigned baseScopeDepth, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, unsigned firstLineColumnOffset, PassOwnPtr<CodeBlock> alternative) 1637 : m_globalObject(globalObject->vm(), ownerExecutable, globalObject) 1638 , m_heap(&m_globalObject->vm().heap) 1639 , m_numCalleeRegisters(unlinkedCodeBlock->m_numCalleeRegisters) 1640 , m_numVars(unlinkedCodeBlock->m_numVars) 1641 , m_isConstructor(unlinkedCodeBlock->isConstructor()) 1642 , m_unlinkedCode(globalObject->vm(), ownerExecutable, unlinkedCodeBlock) 1643 , m_ownerExecutable(globalObject->vm(), ownerExecutable, ownerExecutable) 1644 , m_vm(unlinkedCodeBlock->vm()) 1645 , m_thisRegister(unlinkedCodeBlock->thisRegister()) 1646 , m_argumentsRegister(unlinkedCodeBlock->argumentsRegister()) 1647 , m_activationRegister(unlinkedCodeBlock->activationRegister()) 1648 , m_isStrictMode(unlinkedCodeBlock->isStrictMode()) 1649 , m_needsActivation(unlinkedCodeBlock->needsFullScopeChain()) 1650 , m_source(sourceProvider) 1651 , m_sourceOffset(sourceOffset) 1652 , m_firstLineColumnOffset(firstLineColumnOffset) 1653 , m_codeType(unlinkedCodeBlock->codeType()) 1654 , m_alternative(alternative) 1655 , m_osrExitCounter(0) 1656 , m_optimizationDelayCounter(0) 1657 , m_reoptimizationRetryCounter(0) 1658{ 1659 m_vm->startedCompiling(this); 1660 1661 ASSERT(m_source); 1662 setNumParameters(unlinkedCodeBlock->numParameters()); 1663 1664#if DUMP_CODE_BLOCK_STATISTICS 1665 liveCodeBlockSet.add(this); 1666#endif 1667 setIdentifiers(unlinkedCodeBlock->identifiers()); 1668 setConstantRegisters(unlinkedCodeBlock->constantRegisters()); 1669 if (unlinkedCodeBlock->usesGlobalObject()) 1670 m_constantRegisters[unlinkedCodeBlock->globalObjectRegister()].set(*m_vm, ownerExecutable, globalObject); 1671 m_functionDecls.grow(unlinkedCodeBlock->numberOfFunctionDecls()); 1672 for (size_t count = unlinkedCodeBlock->numberOfFunctionDecls(), i = 0; i < count; ++i) { 1673 UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionDecl(i); 1674 unsigned lineCount = unlinkedExecutable->lineCount(); 1675 unsigned firstLine = ownerExecutable->lineNo() + unlinkedExecutable->firstLineOffset(); 1676 unsigned startColumn = unlinkedExecutable->functionStartColumn(); 1677 startColumn += (unlinkedExecutable->firstLineOffset() ? 1 : ownerExecutable->startColumn()); 1678 unsigned startOffset = sourceOffset + unlinkedExecutable->startOffset(); 1679 unsigned sourceLength = unlinkedExecutable->sourceLength(); 1680 SourceCode code(m_source, startOffset, startOffset + sourceLength, firstLine, startColumn); 1681 FunctionExecutable* executable = FunctionExecutable::create(*m_vm, code, unlinkedExecutable, firstLine, firstLine + lineCount, startColumn); 1682 m_functionDecls[i].set(*m_vm, ownerExecutable, executable); 1683 } 1684 1685 m_functionExprs.grow(unlinkedCodeBlock->numberOfFunctionExprs()); 1686 for (size_t count = unlinkedCodeBlock->numberOfFunctionExprs(), i = 0; i < count; ++i) { 1687 UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionExpr(i); 1688 unsigned lineCount = unlinkedExecutable->lineCount(); 1689 unsigned firstLine = ownerExecutable->lineNo() + unlinkedExecutable->firstLineOffset(); 1690 unsigned startColumn = unlinkedExecutable->functionStartColumn(); 1691 startColumn += (unlinkedExecutable->firstLineOffset() ? 1 : ownerExecutable->startColumn()); 1692 unsigned startOffset = sourceOffset + unlinkedExecutable->startOffset(); 1693 unsigned sourceLength = unlinkedExecutable->sourceLength(); 1694 SourceCode code(m_source, startOffset, startOffset + sourceLength, firstLine, startColumn); 1695 FunctionExecutable* executable = FunctionExecutable::create(*m_vm, code, unlinkedExecutable, firstLine, firstLine + lineCount, startColumn); 1696 m_functionExprs[i].set(*m_vm, ownerExecutable, executable); 1697 } 1698 1699 if (unlinkedCodeBlock->hasRareData()) { 1700 createRareDataIfNecessary(); 1701 if (size_t count = unlinkedCodeBlock->constantBufferCount()) { 1702 m_rareData->m_constantBuffers.grow(count); 1703 for (size_t i = 0; i < count; i++) { 1704 const UnlinkedCodeBlock::ConstantBuffer& buffer = unlinkedCodeBlock->constantBuffer(i); 1705 m_rareData->m_constantBuffers[i] = buffer; 1706 } 1707 } 1708 if (size_t count = unlinkedCodeBlock->numberOfExceptionHandlers()) { 1709 m_rareData->m_exceptionHandlers.grow(count); 1710 for (size_t i = 0; i < count; i++) { 1711 const UnlinkedHandlerInfo& handler = unlinkedCodeBlock->exceptionHandler(i); 1712 m_rareData->m_exceptionHandlers[i].start = handler.start; 1713 m_rareData->m_exceptionHandlers[i].end = handler.end; 1714 m_rareData->m_exceptionHandlers[i].target = handler.target; 1715 m_rareData->m_exceptionHandlers[i].scopeDepth = handler.scopeDepth + baseScopeDepth; 1716#if ENABLE(JIT) && ENABLE(LLINT) 1717 m_rareData->m_exceptionHandlers[i].nativeCode = CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(LLInt::getCodePtr(llint_op_catch))); 1718#endif 1719 } 1720 } 1721 1722 if (size_t count = unlinkedCodeBlock->numberOfStringSwitchJumpTables()) { 1723 m_rareData->m_stringSwitchJumpTables.grow(count); 1724 for (size_t i = 0; i < count; i++) { 1725 UnlinkedStringJumpTable::StringOffsetTable::iterator ptr = unlinkedCodeBlock->stringSwitchJumpTable(i).offsetTable.begin(); 1726 UnlinkedStringJumpTable::StringOffsetTable::iterator end = unlinkedCodeBlock->stringSwitchJumpTable(i).offsetTable.end(); 1727 for (; ptr != end; ++ptr) { 1728 OffsetLocation offset; 1729 offset.branchOffset = ptr->value; 1730 m_rareData->m_stringSwitchJumpTables[i].offsetTable.add(ptr->key, offset); 1731 } 1732 } 1733 } 1734 1735 if (size_t count = unlinkedCodeBlock->numberOfImmediateSwitchJumpTables()) { 1736 m_rareData->m_immediateSwitchJumpTables.grow(count); 1737 for (size_t i = 0; i < count; i++) { 1738 UnlinkedSimpleJumpTable& sourceTable = unlinkedCodeBlock->immediateSwitchJumpTable(i); 1739 SimpleJumpTable& destTable = m_rareData->m_immediateSwitchJumpTables[i]; 1740 destTable.branchOffsets = sourceTable.branchOffsets; 1741 destTable.min = sourceTable.min; 1742 } 1743 } 1744 1745 if (size_t count = unlinkedCodeBlock->numberOfCharacterSwitchJumpTables()) { 1746 m_rareData->m_characterSwitchJumpTables.grow(count); 1747 for (size_t i = 0; i < count; i++) { 1748 UnlinkedSimpleJumpTable& sourceTable = unlinkedCodeBlock->characterSwitchJumpTable(i); 1749 SimpleJumpTable& destTable = m_rareData->m_characterSwitchJumpTables[i]; 1750 destTable.branchOffsets = sourceTable.branchOffsets; 1751 destTable.min = sourceTable.min; 1752 } 1753 } 1754 } 1755 1756 // Allocate metadata buffers for the bytecode 1757#if ENABLE(LLINT) 1758 if (size_t size = unlinkedCodeBlock->numberOfLLintCallLinkInfos()) 1759 m_llintCallLinkInfos.grow(size); 1760#endif 1761#if ENABLE(DFG_JIT) 1762 if (size_t size = unlinkedCodeBlock->numberOfArrayProfiles()) 1763 m_arrayProfiles.grow(size); 1764 if (size_t size = unlinkedCodeBlock->numberOfArrayAllocationProfiles()) 1765 m_arrayAllocationProfiles.grow(size); 1766 if (size_t size = unlinkedCodeBlock->numberOfValueProfiles()) 1767 m_valueProfiles.grow(size); 1768#endif 1769 if (size_t size = unlinkedCodeBlock->numberOfObjectAllocationProfiles()) 1770 m_objectAllocationProfiles.grow(size); 1771 if (size_t size = unlinkedCodeBlock->numberOfResolveOperations()) 1772 m_resolveOperations.grow(size); 1773 if (size_t putToBaseCount = unlinkedCodeBlock->numberOfPutToBaseOperations()) { 1774 m_putToBaseOperations.reserveInitialCapacity(putToBaseCount); 1775 for (size_t i = 0; i < putToBaseCount; ++i) 1776 m_putToBaseOperations.uncheckedAppend(PutToBaseOperation(isStrictMode())); 1777 } 1778 1779 // Copy and translate the UnlinkedInstructions 1780 size_t instructionCount = unlinkedCodeBlock->instructions().size(); 1781 UnlinkedInstruction* pc = unlinkedCodeBlock->instructions().data(); 1782 Vector<Instruction, 0, UnsafeVectorOverflow> instructions(instructionCount); 1783 for (size_t i = 0; i < unlinkedCodeBlock->instructions().size(); ) { 1784 unsigned opLength = opcodeLength(pc[i].u.opcode); 1785 instructions[i] = vm()->interpreter->getOpcode(pc[i].u.opcode); 1786 for (size_t j = 1; j < opLength; ++j) { 1787 if (sizeof(int32_t) != sizeof(intptr_t)) 1788 instructions[i + j].u.pointer = 0; 1789 instructions[i + j].u.operand = pc[i + j].u.operand; 1790 } 1791 switch (pc[i].u.opcode) { 1792#if ENABLE(DFG_JIT) 1793 case op_get_by_val: 1794 case op_get_argument_by_val: { 1795 int arrayProfileIndex = pc[i + opLength - 2].u.operand; 1796 m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i); 1797 1798 instructions[i + opLength - 2] = &m_arrayProfiles[arrayProfileIndex]; 1799 // fallthrough 1800 } 1801 case op_convert_this: 1802 case op_get_by_id: 1803 case op_call_put_result: 1804 case op_get_callee: { 1805 ValueProfile* profile = &m_valueProfiles[pc[i + opLength - 1].u.operand]; 1806 ASSERT(profile->m_bytecodeOffset == -1); 1807 profile->m_bytecodeOffset = i; 1808 instructions[i + opLength - 1] = profile; 1809 break; 1810 } 1811 case op_put_by_val: { 1812 int arrayProfileIndex = pc[i + opLength - 1].u.operand; 1813 m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i); 1814 instructions[i + opLength - 1] = &m_arrayProfiles[arrayProfileIndex]; 1815 break; 1816 } 1817 1818 case op_new_array: 1819 case op_new_array_buffer: 1820 case op_new_array_with_size: { 1821 int arrayAllocationProfileIndex = pc[i + opLength - 1].u.operand; 1822 instructions[i + opLength - 1] = &m_arrayAllocationProfiles[arrayAllocationProfileIndex]; 1823 break; 1824 } 1825#endif 1826 case op_resolve_base: 1827 case op_resolve_base_to_global: 1828 case op_resolve_base_to_global_dynamic: 1829 case op_resolve_base_to_scope: 1830 case op_resolve_base_to_scope_with_top_scope_check: { 1831 instructions[i + 4].u.resolveOperations = &m_resolveOperations[pc[i + 4].u.operand]; 1832 instructions[i + 5].u.putToBaseOperation = &m_putToBaseOperations[pc[i + 5].u.operand]; 1833#if ENABLE(DFG_JIT) 1834 ValueProfile* profile = &m_valueProfiles[pc[i + opLength - 1].u.operand]; 1835 ASSERT(profile->m_bytecodeOffset == -1); 1836 profile->m_bytecodeOffset = i; 1837 ASSERT((opLength - 1) > 5); 1838 instructions[i + opLength - 1] = profile; 1839#endif 1840 break; 1841 } 1842 case op_resolve_global_property: 1843 case op_resolve_global_var: 1844 case op_resolve_scoped_var: 1845 case op_resolve_scoped_var_on_top_scope: 1846 case op_resolve_scoped_var_with_top_scope_check: { 1847 instructions[i + 3].u.resolveOperations = &m_resolveOperations[pc[i + 3].u.operand]; 1848 break; 1849 } 1850 case op_put_to_base: 1851 case op_put_to_base_variable: { 1852 instructions[i + 4].u.putToBaseOperation = &m_putToBaseOperations[pc[i + 4].u.operand]; 1853 break; 1854 } 1855 case op_resolve: { 1856#if ENABLE(DFG_JIT) 1857 ValueProfile* profile = &m_valueProfiles[pc[i + opLength - 1].u.operand]; 1858 ASSERT(profile->m_bytecodeOffset == -1); 1859 profile->m_bytecodeOffset = i; 1860 ASSERT((opLength - 1) > 3); 1861 instructions[i + opLength - 1] = profile; 1862#endif 1863 instructions[i + 3].u.resolveOperations = &m_resolveOperations[pc[i + 3].u.operand]; 1864 break; 1865 } 1866 case op_resolve_with_base: 1867 case op_resolve_with_this: { 1868 instructions[i + 4].u.resolveOperations = &m_resolveOperations[pc[i + 4].u.operand]; 1869 if (pc[i].u.opcode != op_resolve_with_this) 1870 instructions[i + 5].u.putToBaseOperation = &m_putToBaseOperations[pc[i + 5].u.operand]; 1871#if ENABLE(DFG_JIT) 1872 ValueProfile* profile = &m_valueProfiles[pc[i + opLength - 1].u.operand]; 1873 ASSERT(profile->m_bytecodeOffset == -1); 1874 profile->m_bytecodeOffset = i; 1875 instructions[i + opLength - 1] = profile; 1876#endif 1877 break; 1878 } 1879 case op_new_object: { 1880 int objectAllocationProfileIndex = pc[i + opLength - 1].u.operand; 1881 ObjectAllocationProfile* objectAllocationProfile = &m_objectAllocationProfiles[objectAllocationProfileIndex]; 1882 int inferredInlineCapacity = pc[i + opLength - 2].u.operand; 1883 1884 instructions[i + opLength - 1] = objectAllocationProfile; 1885 objectAllocationProfile->initialize(*vm(), 1886 m_ownerExecutable.get(), m_globalObject->objectPrototype(), inferredInlineCapacity); 1887 break; 1888 } 1889 1890 case op_get_scoped_var: { 1891#if ENABLE(DFG_JIT) 1892 ValueProfile* profile = &m_valueProfiles[pc[i + opLength - 1].u.operand]; 1893 ASSERT(profile->m_bytecodeOffset == -1); 1894 profile->m_bytecodeOffset = i; 1895 instructions[i + opLength - 1] = profile; 1896#endif 1897 break; 1898 } 1899 1900 case op_call: 1901 case op_call_eval: { 1902#if ENABLE(DFG_JIT) 1903 int arrayProfileIndex = pc[i + opLength - 1].u.operand; 1904 m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i); 1905 instructions[i + opLength - 1] = &m_arrayProfiles[arrayProfileIndex]; 1906#endif 1907#if ENABLE(LLINT) 1908 instructions[i + 4] = &m_llintCallLinkInfos[pc[i + 4].u.operand]; 1909#endif 1910 break; 1911 } 1912 case op_construct: 1913#if ENABLE(LLINT) 1914 instructions[i + 4] = &m_llintCallLinkInfos[pc[i + 4].u.operand]; 1915#endif 1916 break; 1917 case op_get_by_id_out_of_line: 1918 case op_get_by_id_self: 1919 case op_get_by_id_proto: 1920 case op_get_by_id_chain: 1921 case op_get_by_id_getter_self: 1922 case op_get_by_id_getter_proto: 1923 case op_get_by_id_getter_chain: 1924 case op_get_by_id_custom_self: 1925 case op_get_by_id_custom_proto: 1926 case op_get_by_id_custom_chain: 1927 case op_get_by_id_generic: 1928 case op_get_array_length: 1929 case op_get_string_length: 1930 CRASH(); 1931 1932 case op_init_global_const_nop: { 1933 ASSERT(codeType() == GlobalCode); 1934 Identifier ident = identifier(pc[i + 4].u.operand); 1935 SymbolTableEntry entry = globalObject->symbolTable()->get(ident.impl()); 1936 if (entry.isNull()) 1937 break; 1938 1939 if (entry.couldBeWatched()) { 1940 instructions[i + 0] = vm()->interpreter->getOpcode(op_init_global_const_check); 1941 instructions[i + 1] = &globalObject->registerAt(entry.getIndex()); 1942 instructions[i + 3] = entry.addressOfIsWatched(); 1943 break; 1944 } 1945 1946 instructions[i + 0] = vm()->interpreter->getOpcode(op_init_global_const); 1947 instructions[i + 1] = &globalObject->registerAt(entry.getIndex()); 1948 break; 1949 } 1950 1951 case op_debug: { 1952 instructions[i + 4] = columnNumberForBytecodeOffset(i); 1953 break; 1954 } 1955 1956 default: 1957 break; 1958 } 1959 i += opLength; 1960 } 1961 m_instructions = WTF::RefCountedArray<Instruction>(instructions); 1962 1963 // Set optimization thresholds only after m_instructions is initialized, since these 1964 // rely on the instruction count (and are in theory permitted to also inspect the 1965 // instruction stream to more accurate assess the cost of tier-up). 1966 optimizeAfterWarmUp(); 1967 jitAfterWarmUp(); 1968 1969 if (Options::dumpGeneratedBytecodes()) 1970 dumpBytecode(); 1971 m_vm->finishedCompiling(this); 1972} 1973 1974CodeBlock::~CodeBlock() 1975{ 1976 if (m_vm->m_perBytecodeProfiler) 1977 m_vm->m_perBytecodeProfiler->notifyDestruction(this); 1978 1979#if ENABLE(DFG_JIT) 1980 // Remove myself from the set of DFG code blocks. Note that I may not be in this set 1981 // (because I'm not a DFG code block), in which case this is a no-op anyway. 1982 m_vm->heap.m_dfgCodeBlocks.m_set.remove(this); 1983#endif 1984 1985#if ENABLE(VERBOSE_VALUE_PROFILE) 1986 dumpValueProfiles(); 1987#endif 1988 1989#if ENABLE(LLINT) 1990 while (m_incomingLLIntCalls.begin() != m_incomingLLIntCalls.end()) 1991 m_incomingLLIntCalls.begin()->remove(); 1992#endif // ENABLE(LLINT) 1993#if ENABLE(JIT) 1994 // We may be destroyed before any CodeBlocks that refer to us are destroyed. 1995 // Consider that two CodeBlocks become unreachable at the same time. There 1996 // is no guarantee about the order in which the CodeBlocks are destroyed. 1997 // So, if we don't remove incoming calls, and get destroyed before the 1998 // CodeBlock(s) that have calls into us, then the CallLinkInfo vector's 1999 // destructor will try to remove nodes from our (no longer valid) linked list. 2000 while (m_incomingCalls.begin() != m_incomingCalls.end()) 2001 m_incomingCalls.begin()->remove(); 2002 2003 // Note that our outgoing calls will be removed from other CodeBlocks' 2004 // m_incomingCalls linked lists through the execution of the ~CallLinkInfo 2005 // destructors. 2006 2007 for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i) 2008 m_structureStubInfos[i].deref(); 2009#endif // ENABLE(JIT) 2010 2011#if DUMP_CODE_BLOCK_STATISTICS 2012 liveCodeBlockSet.remove(this); 2013#endif 2014} 2015 2016void CodeBlock::setNumParameters(int newValue) 2017{ 2018 m_numParameters = newValue; 2019 2020#if ENABLE(VALUE_PROFILER) 2021 m_argumentValueProfiles.resizeToFit(newValue); 2022#endif 2023} 2024 2025void CodeBlock::visitStructures(SlotVisitor& visitor, Instruction* vPC) 2026{ 2027 Interpreter* interpreter = m_vm->interpreter; 2028 2029 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) && vPC[4].u.structure) { 2030 visitor.append(&vPC[4].u.structure); 2031 return; 2032 } 2033 2034 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_self)) { 2035 visitor.append(&vPC[4].u.structure); 2036 return; 2037 } 2038 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_proto)) { 2039 visitor.append(&vPC[4].u.structure); 2040 visitor.append(&vPC[5].u.structure); 2041 return; 2042 } 2043 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_chain)) { 2044 visitor.append(&vPC[4].u.structure); 2045 if (vPC[5].u.structureChain) 2046 visitor.append(&vPC[5].u.structureChain); 2047 return; 2048 } 2049 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) { 2050 visitor.append(&vPC[4].u.structure); 2051 visitor.append(&vPC[5].u.structure); 2052 if (vPC[6].u.structureChain) 2053 visitor.append(&vPC[6].u.structureChain); 2054 return; 2055 } 2056 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) && vPC[4].u.structure) { 2057 visitor.append(&vPC[4].u.structure); 2058 return; 2059 } 2060 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) { 2061 visitor.append(&vPC[4].u.structure); 2062 return; 2063 } 2064 2065 // These instructions don't ref their Structures. 2066 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)); 2067} 2068 2069void EvalCodeCache::visitAggregate(SlotVisitor& visitor) 2070{ 2071 EvalCacheMap::iterator end = m_cacheMap.end(); 2072 for (EvalCacheMap::iterator ptr = m_cacheMap.begin(); ptr != end; ++ptr) 2073 visitor.append(&ptr->value); 2074} 2075 2076void CodeBlock::visitAggregate(SlotVisitor& visitor) 2077{ 2078#if ENABLE(PARALLEL_GC) && ENABLE(DFG_JIT) 2079 if (!!m_dfgData) { 2080 // I may be asked to scan myself more than once, and it may even happen concurrently. 2081 // To this end, use a CAS loop to check if I've been called already. Only one thread 2082 // may proceed past this point - whichever one wins the CAS race. 2083 unsigned oldValue; 2084 do { 2085 oldValue = m_dfgData->visitAggregateHasBeenCalled; 2086 if (oldValue) { 2087 // Looks like someone else won! Return immediately to ensure that we don't 2088 // trace the same CodeBlock concurrently. Doing so is hazardous since we will 2089 // be mutating the state of ValueProfiles, which contain JSValues, which can 2090 // have word-tearing on 32-bit, leading to awesome timing-dependent crashes 2091 // that are nearly impossible to track down. 2092 2093 // Also note that it must be safe to return early as soon as we see the 2094 // value true (well, (unsigned)1), since once a GC thread is in this method 2095 // and has won the CAS race (i.e. was responsible for setting the value true) 2096 // it will definitely complete the rest of this method before declaring 2097 // termination. 2098 return; 2099 } 2100 } while (!WTF::weakCompareAndSwap(&m_dfgData->visitAggregateHasBeenCalled, 0, 1)); 2101 } 2102#endif // ENABLE(PARALLEL_GC) && ENABLE(DFG_JIT) 2103 2104 if (!!m_alternative) 2105 m_alternative->visitAggregate(visitor); 2106 2107 visitor.append(&m_unlinkedCode); 2108 2109 // There are three things that may use unconditional finalizers: lazy bytecode freeing, 2110 // inline cache clearing, and jettisoning. The probability of us wanting to do at 2111 // least one of those things is probably quite close to 1. So we add one no matter what 2112 // and when it runs, it figures out whether it has any work to do. 2113 visitor.addUnconditionalFinalizer(this); 2114 2115 if (shouldImmediatelyAssumeLivenessDuringScan()) { 2116 // This code block is live, so scan all references strongly and return. 2117 stronglyVisitStrongReferences(visitor); 2118 stronglyVisitWeakReferences(visitor); 2119 return; 2120 } 2121 2122#if ENABLE(DFG_JIT) 2123 // We get here if we're live in the sense that our owner executable is live, 2124 // but we're not yet live for sure in another sense: we may yet decide that this 2125 // code block should be jettisoned based on its outgoing weak references being 2126 // stale. Set a flag to indicate that we're still assuming that we're dead, and 2127 // perform one round of determining if we're live. The GC may determine, based on 2128 // either us marking additional objects, or by other objects being marked for 2129 // other reasons, that this iteration should run again; it will notify us of this 2130 // decision by calling harvestWeakReferences(). 2131 2132 m_dfgData->livenessHasBeenProved = false; 2133 m_dfgData->allTransitionsHaveBeenMarked = false; 2134 2135 performTracingFixpointIteration(visitor); 2136 2137 // GC doesn't have enough information yet for us to decide whether to keep our DFG 2138 // data, so we need to register a handler to run again at the end of GC, when more 2139 // information is available. 2140 if (!(m_dfgData->livenessHasBeenProved && m_dfgData->allTransitionsHaveBeenMarked)) 2141 visitor.addWeakReferenceHarvester(this); 2142 2143#else // ENABLE(DFG_JIT) 2144 RELEASE_ASSERT_NOT_REACHED(); 2145#endif // ENABLE(DFG_JIT) 2146} 2147 2148void CodeBlock::performTracingFixpointIteration(SlotVisitor& visitor) 2149{ 2150 UNUSED_PARAM(visitor); 2151 2152#if ENABLE(DFG_JIT) 2153 // Evaluate our weak reference transitions, if there are still some to evaluate. 2154 if (!m_dfgData->allTransitionsHaveBeenMarked) { 2155 bool allAreMarkedSoFar = true; 2156 for (unsigned i = 0; i < m_dfgData->transitions.size(); ++i) { 2157 if ((!m_dfgData->transitions[i].m_codeOrigin 2158 || Heap::isMarked(m_dfgData->transitions[i].m_codeOrigin.get())) 2159 && Heap::isMarked(m_dfgData->transitions[i].m_from.get())) { 2160 // If the following three things are live, then the target of the 2161 // transition is also live: 2162 // - This code block. We know it's live already because otherwise 2163 // we wouldn't be scanning ourselves. 2164 // - The code origin of the transition. Transitions may arise from 2165 // code that was inlined. They are not relevant if the user's 2166 // object that is required for the inlinee to run is no longer 2167 // live. 2168 // - The source of the transition. The transition checks if some 2169 // heap location holds the source, and if so, stores the target. 2170 // Hence the source must be live for the transition to be live. 2171 visitor.append(&m_dfgData->transitions[i].m_to); 2172 } else 2173 allAreMarkedSoFar = false; 2174 } 2175 2176 if (allAreMarkedSoFar) 2177 m_dfgData->allTransitionsHaveBeenMarked = true; 2178 } 2179 2180 // Check if we have any remaining work to do. 2181 if (m_dfgData->livenessHasBeenProved) 2182 return; 2183 2184 // Now check all of our weak references. If all of them are live, then we 2185 // have proved liveness and so we scan our strong references. If at end of 2186 // GC we still have not proved liveness, then this code block is toast. 2187 bool allAreLiveSoFar = true; 2188 for (unsigned i = 0; i < m_dfgData->weakReferences.size(); ++i) { 2189 if (!Heap::isMarked(m_dfgData->weakReferences[i].get())) { 2190 allAreLiveSoFar = false; 2191 break; 2192 } 2193 } 2194 2195 // If some weak references are dead, then this fixpoint iteration was 2196 // unsuccessful. 2197 if (!allAreLiveSoFar) 2198 return; 2199 2200 // All weak references are live. Record this information so we don't 2201 // come back here again, and scan the strong references. 2202 m_dfgData->livenessHasBeenProved = true; 2203 stronglyVisitStrongReferences(visitor); 2204#endif // ENABLE(DFG_JIT) 2205} 2206 2207void CodeBlock::visitWeakReferences(SlotVisitor& visitor) 2208{ 2209 performTracingFixpointIteration(visitor); 2210} 2211 2212#if ENABLE(JIT_VERBOSE_OSR) 2213static const bool verboseUnlinking = true; 2214#else 2215static const bool verboseUnlinking = false; 2216#endif 2217 2218void CodeBlock::finalizeUnconditionally() 2219{ 2220#if ENABLE(LLINT) 2221 Interpreter* interpreter = m_vm->interpreter; 2222 if (!!numberOfInstructions()) { 2223 const Vector<unsigned>& propertyAccessInstructions = m_unlinkedCode->propertyAccessInstructions(); 2224 for (size_t size = propertyAccessInstructions.size(), i = 0; i < size; ++i) { 2225 Instruction* curInstruction = &instructions()[propertyAccessInstructions[i]]; 2226 switch (interpreter->getOpcodeID(curInstruction[0].u.opcode)) { 2227 case op_get_by_id: 2228 case op_get_by_id_out_of_line: 2229 case op_put_by_id: 2230 case op_put_by_id_out_of_line: 2231 if (!curInstruction[4].u.structure || Heap::isMarked(curInstruction[4].u.structure.get())) 2232 break; 2233 if (verboseUnlinking) 2234 dataLogF("Clearing LLInt property access with structure %p.\n", curInstruction[4].u.structure.get()); 2235 curInstruction[4].u.structure.clear(); 2236 curInstruction[5].u.operand = 0; 2237 break; 2238 case op_put_by_id_transition_direct: 2239 case op_put_by_id_transition_normal: 2240 case op_put_by_id_transition_direct_out_of_line: 2241 case op_put_by_id_transition_normal_out_of_line: 2242 if (Heap::isMarked(curInstruction[4].u.structure.get()) 2243 && Heap::isMarked(curInstruction[6].u.structure.get()) 2244 && Heap::isMarked(curInstruction[7].u.structureChain.get())) 2245 break; 2246 if (verboseUnlinking) { 2247 dataLogF("Clearing LLInt put transition with structures %p -> %p, chain %p.\n", 2248 curInstruction[4].u.structure.get(), 2249 curInstruction[6].u.structure.get(), 2250 curInstruction[7].u.structureChain.get()); 2251 } 2252 curInstruction[4].u.structure.clear(); 2253 curInstruction[6].u.structure.clear(); 2254 curInstruction[7].u.structureChain.clear(); 2255 curInstruction[0].u.opcode = interpreter->getOpcode(op_put_by_id); 2256 break; 2257 case op_get_array_length: 2258 break; 2259 default: 2260 RELEASE_ASSERT_NOT_REACHED(); 2261 } 2262 } 2263 2264 for (unsigned i = 0; i < m_llintCallLinkInfos.size(); ++i) { 2265 if (m_llintCallLinkInfos[i].isLinked() && !Heap::isMarked(m_llintCallLinkInfos[i].callee.get())) { 2266 if (verboseUnlinking) 2267 dataLog("Clearing LLInt call from ", *this, "\n"); 2268 m_llintCallLinkInfos[i].unlink(); 2269 } 2270 if (!!m_llintCallLinkInfos[i].lastSeenCallee && !Heap::isMarked(m_llintCallLinkInfos[i].lastSeenCallee.get())) 2271 m_llintCallLinkInfos[i].lastSeenCallee.clear(); 2272 } 2273 } 2274#endif // ENABLE(LLINT) 2275 2276#if ENABLE(DFG_JIT) 2277 // Check if we're not live. If we are, then jettison. 2278 if (!(shouldImmediatelyAssumeLivenessDuringScan() || m_dfgData->livenessHasBeenProved)) { 2279 if (verboseUnlinking) 2280 dataLog(*this, " has dead weak references, jettisoning during GC.\n"); 2281 2282 if (DFG::shouldShowDisassembly()) { 2283 dataLog(*this, " will be jettisoned because of the following dead references:\n"); 2284 for (unsigned i = 0; i < m_dfgData->transitions.size(); ++i) { 2285 WeakReferenceTransition& transition = m_dfgData->transitions[i]; 2286 JSCell* origin = transition.m_codeOrigin.get(); 2287 JSCell* from = transition.m_from.get(); 2288 JSCell* to = transition.m_to.get(); 2289 if ((!origin || Heap::isMarked(origin)) && Heap::isMarked(from)) 2290 continue; 2291 dataLog(" Transition under ", JSValue(origin), ", ", JSValue(from), " -> ", JSValue(to), ".\n"); 2292 } 2293 for (unsigned i = 0; i < m_dfgData->weakReferences.size(); ++i) { 2294 JSCell* weak = m_dfgData->weakReferences[i].get(); 2295 if (Heap::isMarked(weak)) 2296 continue; 2297 dataLog(" Weak reference ", JSValue(weak), ".\n"); 2298 } 2299 } 2300 2301 jettison(); 2302 return; 2303 } 2304#endif // ENABLE(DFG_JIT) 2305 2306 for (size_t size = m_putToBaseOperations.size(), i = 0; i < size; ++i) { 2307 if (m_putToBaseOperations[i].m_structure && !Heap::isMarked(m_putToBaseOperations[i].m_structure.get())) { 2308 if (verboseUnlinking) 2309 dataLog("Clearing putToBase info in ", *this, "\n"); 2310 m_putToBaseOperations[i].m_structure.clear(); 2311 } 2312 } 2313 for (size_t size = m_resolveOperations.size(), i = 0; i < size; ++i) { 2314 if (m_resolveOperations[i].isEmpty()) 2315 continue; 2316#ifndef NDEBUG 2317 for (size_t insnSize = m_resolveOperations[i].size() - 1, k = 0; k < insnSize; ++k) 2318 ASSERT(!m_resolveOperations[i][k].m_structure); 2319#endif 2320 m_resolveOperations[i].last().m_structure.clear(); 2321 if (m_resolveOperations[i].last().m_structure && !Heap::isMarked(m_resolveOperations[i].last().m_structure.get())) { 2322 if (verboseUnlinking) 2323 dataLog("Clearing resolve info in ", *this, "\n"); 2324 m_resolveOperations[i].last().m_structure.clear(); 2325 } 2326 } 2327 2328#if ENABLE(JIT) 2329 // Handle inline caches. 2330 if (!!getJITCode()) { 2331 RepatchBuffer repatchBuffer(this); 2332 for (unsigned i = 0; i < numberOfCallLinkInfos(); ++i) { 2333 if (callLinkInfo(i).isLinked()) { 2334 if (ClosureCallStubRoutine* stub = callLinkInfo(i).stub.get()) { 2335 if (!Heap::isMarked(stub->structure()) 2336 || !Heap::isMarked(stub->executable())) { 2337 if (verboseUnlinking) { 2338 dataLog( 2339 "Clearing closure call from ", *this, " to ", 2340 stub->executable()->hashFor(callLinkInfo(i).specializationKind()), 2341 ", stub routine ", RawPointer(stub), ".\n"); 2342 } 2343 callLinkInfo(i).unlink(*m_vm, repatchBuffer); 2344 } 2345 } else if (!Heap::isMarked(callLinkInfo(i).callee.get())) { 2346 if (verboseUnlinking) { 2347 dataLog( 2348 "Clearing call from ", *this, " to ", 2349 RawPointer(callLinkInfo(i).callee.get()), " (", 2350 callLinkInfo(i).callee.get()->executable()->hashFor( 2351 callLinkInfo(i).specializationKind()), 2352 ").\n"); 2353 } 2354 callLinkInfo(i).unlink(*m_vm, repatchBuffer); 2355 } 2356 } 2357 if (!!callLinkInfo(i).lastSeenCallee 2358 && !Heap::isMarked(callLinkInfo(i).lastSeenCallee.get())) 2359 callLinkInfo(i).lastSeenCallee.clear(); 2360 } 2361 for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i) { 2362 StructureStubInfo& stubInfo = m_structureStubInfos[i]; 2363 2364 if (stubInfo.visitWeakReferences()) 2365 continue; 2366 2367 resetStubDuringGCInternal(repatchBuffer, stubInfo); 2368 } 2369 } 2370#endif 2371} 2372 2373#if ENABLE(JIT) 2374void CodeBlock::resetStub(StructureStubInfo& stubInfo) 2375{ 2376 if (stubInfo.accessType == access_unset) 2377 return; 2378 2379 RepatchBuffer repatchBuffer(this); 2380 resetStubInternal(repatchBuffer, stubInfo); 2381} 2382 2383void CodeBlock::resetStubInternal(RepatchBuffer& repatchBuffer, StructureStubInfo& stubInfo) 2384{ 2385 AccessType accessType = static_cast<AccessType>(stubInfo.accessType); 2386 2387 if (verboseUnlinking) 2388 dataLog("Clearing structure cache (kind ", static_cast<int>(stubInfo.accessType), ") in ", *this, ".\n"); 2389 2390 if (isGetByIdAccess(accessType)) { 2391 if (getJITCode().jitType() == JITCode::DFGJIT) 2392 DFG::dfgResetGetByID(repatchBuffer, stubInfo); 2393 else 2394 JIT::resetPatchGetById(repatchBuffer, &stubInfo); 2395 } else { 2396 ASSERT(isPutByIdAccess(accessType)); 2397 if (getJITCode().jitType() == JITCode::DFGJIT) 2398 DFG::dfgResetPutByID(repatchBuffer, stubInfo); 2399 else 2400 JIT::resetPatchPutById(repatchBuffer, &stubInfo); 2401 } 2402 2403 stubInfo.reset(); 2404} 2405 2406void CodeBlock::resetStubDuringGCInternal(RepatchBuffer& repatchBuffer, StructureStubInfo& stubInfo) 2407{ 2408 resetStubInternal(repatchBuffer, stubInfo); 2409 stubInfo.resetByGC = true; 2410} 2411#endif 2412 2413void CodeBlock::stronglyVisitStrongReferences(SlotVisitor& visitor) 2414{ 2415 visitor.append(&m_globalObject); 2416 visitor.append(&m_ownerExecutable); 2417 visitor.append(&m_unlinkedCode); 2418 if (m_rareData) 2419 m_rareData->m_evalCodeCache.visitAggregate(visitor); 2420 visitor.appendValues(m_constantRegisters.data(), m_constantRegisters.size()); 2421 for (size_t i = 0; i < m_functionExprs.size(); ++i) 2422 visitor.append(&m_functionExprs[i]); 2423 for (size_t i = 0; i < m_functionDecls.size(); ++i) 2424 visitor.append(&m_functionDecls[i]); 2425 for (unsigned i = 0; i < m_objectAllocationProfiles.size(); ++i) 2426 m_objectAllocationProfiles[i].visitAggregate(visitor); 2427 2428 updateAllPredictions(Collection); 2429} 2430 2431void CodeBlock::stronglyVisitWeakReferences(SlotVisitor& visitor) 2432{ 2433 UNUSED_PARAM(visitor); 2434 2435#if ENABLE(DFG_JIT) 2436 if (!m_dfgData) 2437 return; 2438 2439 for (unsigned i = 0; i < m_dfgData->transitions.size(); ++i) { 2440 if (!!m_dfgData->transitions[i].m_codeOrigin) 2441 visitor.append(&m_dfgData->transitions[i].m_codeOrigin); // Almost certainly not necessary, since the code origin should also be a weak reference. Better to be safe, though. 2442 visitor.append(&m_dfgData->transitions[i].m_from); 2443 visitor.append(&m_dfgData->transitions[i].m_to); 2444 } 2445 2446 for (unsigned i = 0; i < m_dfgData->weakReferences.size(); ++i) 2447 visitor.append(&m_dfgData->weakReferences[i]); 2448#endif 2449} 2450 2451HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset) 2452{ 2453 RELEASE_ASSERT(bytecodeOffset < instructions().size()); 2454 2455 if (!m_rareData) 2456 return 0; 2457 2458 Vector<HandlerInfo>& exceptionHandlers = m_rareData->m_exceptionHandlers; 2459 for (size_t i = 0; i < exceptionHandlers.size(); ++i) { 2460 // Handlers are ordered innermost first, so the first handler we encounter 2461 // that contains the source address is the correct handler to use. 2462 if (exceptionHandlers[i].start <= bytecodeOffset && exceptionHandlers[i].end > bytecodeOffset) 2463 return &exceptionHandlers[i]; 2464 } 2465 2466 return 0; 2467} 2468 2469unsigned CodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset) 2470{ 2471 RELEASE_ASSERT(bytecodeOffset < instructions().size()); 2472 return m_ownerExecutable->lineNo() + m_unlinkedCode->lineNumberForBytecodeOffset(bytecodeOffset); 2473} 2474 2475unsigned CodeBlock::columnNumberForBytecodeOffset(unsigned bytecodeOffset) 2476{ 2477 int divot; 2478 int startOffset; 2479 int endOffset; 2480 unsigned line; 2481 unsigned column; 2482 expressionRangeForBytecodeOffset(bytecodeOffset, divot, startOffset, endOffset, line, column); 2483 return column; 2484} 2485 2486void CodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column) 2487{ 2488 m_unlinkedCode->expressionRangeForBytecodeOffset(bytecodeOffset, divot, startOffset, endOffset, line, column); 2489 divot += m_sourceOffset; 2490 column += line ? 1 : firstLineColumnOffset(); 2491 line += m_ownerExecutable->lineNo(); 2492} 2493 2494void CodeBlock::shrinkToFit(ShrinkMode shrinkMode) 2495{ 2496#if ENABLE(LLINT) 2497 m_llintCallLinkInfos.shrinkToFit(); 2498#endif 2499#if ENABLE(JIT) 2500 m_structureStubInfos.shrinkToFit(); 2501 m_callLinkInfos.shrinkToFit(); 2502#endif 2503#if ENABLE(VALUE_PROFILER) 2504 m_rareCaseProfiles.shrinkToFit(); 2505 m_specialFastCaseProfiles.shrinkToFit(); 2506#endif 2507 2508 if (shrinkMode == EarlyShrink) { 2509 m_identifiers.shrinkToFit(); 2510 m_functionDecls.shrinkToFit(); 2511 m_functionExprs.shrinkToFit(); 2512 m_constantRegisters.shrinkToFit(); 2513 } // else don't shrink these, because we would have already pointed pointers into these tables. 2514 2515 if (m_rareData) { 2516 m_rareData->m_exceptionHandlers.shrinkToFit(); 2517 m_rareData->m_immediateSwitchJumpTables.shrinkToFit(); 2518 m_rareData->m_characterSwitchJumpTables.shrinkToFit(); 2519 m_rareData->m_stringSwitchJumpTables.shrinkToFit(); 2520#if ENABLE(JIT) 2521 m_rareData->m_callReturnIndexVector.shrinkToFit(); 2522#endif 2523#if ENABLE(DFG_JIT) 2524 m_rareData->m_inlineCallFrames.shrinkToFit(); 2525 m_rareData->m_codeOrigins.shrinkToFit(); 2526#endif 2527 } 2528 2529#if ENABLE(DFG_JIT) 2530 if (m_dfgData) { 2531 m_dfgData->osrEntry.shrinkToFit(); 2532 m_dfgData->osrExit.shrinkToFit(); 2533 m_dfgData->speculationRecovery.shrinkToFit(); 2534 m_dfgData->weakReferences.shrinkToFit(); 2535 m_dfgData->transitions.shrinkToFit(); 2536 m_dfgData->minifiedDFG.prepareAndShrink(); 2537 m_dfgData->variableEventStream.shrinkToFit(); 2538 } 2539#endif 2540} 2541 2542void CodeBlock::createActivation(CallFrame* callFrame) 2543{ 2544 ASSERT(codeType() == FunctionCode); 2545 ASSERT(needsFullScopeChain()); 2546 ASSERT(!callFrame->uncheckedR(activationRegister()).jsValue()); 2547 JSActivation* activation = JSActivation::create(callFrame->vm(), callFrame, this); 2548 callFrame->uncheckedR(activationRegister()) = JSValue(activation); 2549 callFrame->setScope(activation); 2550} 2551 2552unsigned CodeBlock::addOrFindConstant(JSValue v) 2553{ 2554 unsigned numberOfConstants = numberOfConstantRegisters(); 2555 for (unsigned i = 0; i < numberOfConstants; ++i) { 2556 if (getConstant(FirstConstantRegisterIndex + i) == v) 2557 return i; 2558 } 2559 return addConstant(v); 2560} 2561 2562#if ENABLE(JIT) 2563void CodeBlock::unlinkCalls() 2564{ 2565 if (!!m_alternative) 2566 m_alternative->unlinkCalls(); 2567#if ENABLE(LLINT) 2568 for (size_t i = 0; i < m_llintCallLinkInfos.size(); ++i) { 2569 if (m_llintCallLinkInfos[i].isLinked()) 2570 m_llintCallLinkInfos[i].unlink(); 2571 } 2572#endif 2573 if (!m_callLinkInfos.size()) 2574 return; 2575 if (!m_vm->canUseJIT()) 2576 return; 2577 RepatchBuffer repatchBuffer(this); 2578 for (size_t i = 0; i < m_callLinkInfos.size(); i++) { 2579 if (!m_callLinkInfos[i].isLinked()) 2580 continue; 2581 m_callLinkInfos[i].unlink(*m_vm, repatchBuffer); 2582 } 2583} 2584 2585void CodeBlock::unlinkIncomingCalls() 2586{ 2587#if ENABLE(LLINT) 2588 while (m_incomingLLIntCalls.begin() != m_incomingLLIntCalls.end()) 2589 m_incomingLLIntCalls.begin()->unlink(); 2590#endif 2591 if (m_incomingCalls.isEmpty()) 2592 return; 2593 RepatchBuffer repatchBuffer(this); 2594 while (m_incomingCalls.begin() != m_incomingCalls.end()) 2595 m_incomingCalls.begin()->unlink(*m_vm, repatchBuffer); 2596} 2597#endif // ENABLE(JIT) 2598 2599#if ENABLE(LLINT) 2600Instruction* CodeBlock::adjustPCIfAtCallSite(Instruction* potentialReturnPC) 2601{ 2602 ASSERT(potentialReturnPC); 2603 2604 unsigned returnPCOffset = potentialReturnPC - instructions().begin(); 2605 Instruction* adjustedPC; 2606 unsigned opcodeLength; 2607 2608 // If we are at a callsite, the LLInt stores the PC after the call 2609 // instruction rather than the PC of the call instruction. This requires 2610 // some correcting. If so, we can rely on the fact that the preceding 2611 // instruction must be one of the call instructions, so either it's a 2612 // call_varargs or it's a call, construct, or eval. 2613 // 2614 // If we are not at a call site, then we need to guard against the 2615 // possibility of peeking past the start of the bytecode range for this 2616 // codeBlock. Hence, we do a bounds check before we peek at the 2617 // potential "preceding" instruction. 2618 // The bounds check is done by comparing the offset of the potential 2619 // returnPC with the length of the opcode. If there is room for a call 2620 // instruction before the returnPC, then the offset of the returnPC must 2621 // be greater than the size of the call opcode we're looking for. 2622 2623 // The determination of the call instruction present (if we are at a 2624 // callsite) depends on the following assumptions. So, assert that 2625 // they are still true: 2626 ASSERT(OPCODE_LENGTH(op_call_varargs) <= OPCODE_LENGTH(op_call)); 2627 ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct)); 2628 ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_call_eval)); 2629 2630 // Check for the case of a preceeding op_call_varargs: 2631 opcodeLength = OPCODE_LENGTH(op_call_varargs); 2632 adjustedPC = potentialReturnPC - opcodeLength; 2633 if ((returnPCOffset >= opcodeLength) 2634 && (adjustedPC->u.pointer == LLInt::getCodePtr(llint_op_call_varargs))) { 2635 return adjustedPC; 2636 } 2637 2638 // Check for the case of the other 3 call instructions: 2639 opcodeLength = OPCODE_LENGTH(op_call); 2640 adjustedPC = potentialReturnPC - opcodeLength; 2641 if ((returnPCOffset >= opcodeLength) 2642 && (adjustedPC->u.pointer == LLInt::getCodePtr(llint_op_call) 2643 || adjustedPC->u.pointer == LLInt::getCodePtr(llint_op_construct) 2644 || adjustedPC->u.pointer == LLInt::getCodePtr(llint_op_call_eval))) { 2645 return adjustedPC; 2646 } 2647 2648 // Not a call site. No need to adjust PC. Just return the original. 2649 return potentialReturnPC; 2650} 2651#endif // ENABLE(LLINT) 2652 2653#if ENABLE(JIT) 2654ClosureCallStubRoutine* CodeBlock::findClosureCallForReturnPC(ReturnAddressPtr returnAddress) 2655{ 2656 for (unsigned i = m_callLinkInfos.size(); i--;) { 2657 CallLinkInfo& info = m_callLinkInfos[i]; 2658 if (!info.stub) 2659 continue; 2660 if (!info.stub->code().executableMemory()->contains(returnAddress.value())) 2661 continue; 2662 2663 RELEASE_ASSERT(info.stub->codeOrigin().bytecodeIndex < CodeOrigin::maximumBytecodeIndex); 2664 return info.stub.get(); 2665 } 2666 2667 // The stub routine may have been jettisoned. This is rare, but we have to handle it. 2668 const JITStubRoutineSet& set = m_vm->heap.jitStubRoutines(); 2669 for (unsigned i = set.size(); i--;) { 2670 GCAwareJITStubRoutine* genericStub = set.at(i); 2671 if (!genericStub->isClosureCall()) 2672 continue; 2673 ClosureCallStubRoutine* stub = static_cast<ClosureCallStubRoutine*>(genericStub); 2674 if (!stub->code().executableMemory()->contains(returnAddress.value())) 2675 continue; 2676 RELEASE_ASSERT(stub->codeOrigin().bytecodeIndex < CodeOrigin::maximumBytecodeIndex); 2677 return stub; 2678 } 2679 2680 return 0; 2681} 2682#endif 2683 2684unsigned CodeBlock::bytecodeOffset(ExecState* exec, ReturnAddressPtr returnAddress) 2685{ 2686 UNUSED_PARAM(exec); 2687 UNUSED_PARAM(returnAddress); 2688#if ENABLE(LLINT) 2689#if !ENABLE(LLINT_C_LOOP) 2690 // When using the JIT, we could have addresses that are not bytecode 2691 // addresses. We check if the return address is in the LLint glue and 2692 // opcode handlers range here to ensure that we are looking at bytecode 2693 // before attempting to convert the return address into a bytecode offset. 2694 // 2695 // In the case of the C Loop LLInt, the JIT is disabled, and the only 2696 // valid return addresses should be bytecode PCs. So, we can and need to 2697 // forego this check because when we do not ENABLE(COMPUTED_GOTO_OPCODES), 2698 // then the bytecode "PC"s are actually the opcodeIDs and are not bounded 2699 // by llint_begin and llint_end. 2700 if (returnAddress.value() >= LLInt::getCodePtr(llint_begin) 2701 && returnAddress.value() <= LLInt::getCodePtr(llint_end)) 2702#endif 2703 { 2704 RELEASE_ASSERT(exec->codeBlock()); 2705 RELEASE_ASSERT(exec->codeBlock() == this); 2706 RELEASE_ASSERT(JITCode::isBaselineCode(getJITType())); 2707 Instruction* instruction = exec->currentVPC(); 2708 RELEASE_ASSERT(instruction); 2709 2710 instruction = adjustPCIfAtCallSite(instruction); 2711 return bytecodeOffset(instruction); 2712 } 2713#endif // !ENABLE(LLINT) 2714 2715#if ENABLE(JIT) 2716 if (!m_rareData) 2717 return 1; 2718 Vector<CallReturnOffsetToBytecodeOffset, 0, UnsafeVectorOverflow>& callIndices = m_rareData->m_callReturnIndexVector; 2719 if (!callIndices.size()) 2720 return 1; 2721 2722 if (getJITCode().getExecutableMemory()->contains(returnAddress.value())) { 2723 unsigned callReturnOffset = getJITCode().offsetOf(returnAddress.value()); 2724 CallReturnOffsetToBytecodeOffset* result = 2725 binarySearch<CallReturnOffsetToBytecodeOffset, unsigned>( 2726 callIndices, callIndices.size(), callReturnOffset, getCallReturnOffset); 2727 RELEASE_ASSERT(result->callReturnOffset == callReturnOffset); 2728 RELEASE_ASSERT(result->bytecodeOffset < instructionCount()); 2729 return result->bytecodeOffset; 2730 } 2731 ClosureCallStubRoutine* closureInfo = findClosureCallForReturnPC(returnAddress); 2732 CodeOrigin origin = closureInfo->codeOrigin(); 2733 while (InlineCallFrame* inlineCallFrame = origin.inlineCallFrame) { 2734 if (inlineCallFrame->baselineCodeBlock() == this) 2735 break; 2736 origin = inlineCallFrame->caller; 2737 RELEASE_ASSERT(origin.bytecodeIndex < CodeOrigin::maximumBytecodeIndex); 2738 } 2739 RELEASE_ASSERT(origin.bytecodeIndex < CodeOrigin::maximumBytecodeIndex); 2740 unsigned bytecodeIndex = origin.bytecodeIndex; 2741 RELEASE_ASSERT(bytecodeIndex < instructionCount()); 2742 return bytecodeIndex; 2743#endif // ENABLE(JIT) 2744 2745#if !ENABLE(LLINT) && !ENABLE(JIT) 2746 return 1; 2747#endif 2748} 2749 2750#if ENABLE(DFG_JIT) 2751bool CodeBlock::codeOriginForReturn(ReturnAddressPtr returnAddress, CodeOrigin& codeOrigin) 2752{ 2753 if (!hasCodeOrigins()) 2754 return false; 2755 2756 if (!getJITCode().getExecutableMemory()->contains(returnAddress.value())) { 2757 ClosureCallStubRoutine* stub = findClosureCallForReturnPC(returnAddress); 2758 ASSERT(stub); 2759 if (!stub) 2760 return false; 2761 codeOrigin = stub->codeOrigin(); 2762 return true; 2763 } 2764 2765 unsigned offset = getJITCode().offsetOf(returnAddress.value()); 2766 CodeOriginAtCallReturnOffset* entry = 2767 tryBinarySearch<CodeOriginAtCallReturnOffset, unsigned>( 2768 codeOrigins(), codeOrigins().size(), offset, 2769 getCallReturnOffsetForCodeOrigin); 2770 if (!entry) 2771 return false; 2772 codeOrigin = entry->codeOrigin; 2773 return true; 2774} 2775#endif // ENABLE(DFG_JIT) 2776 2777void CodeBlock::clearEvalCache() 2778{ 2779 if (!!m_alternative) 2780 m_alternative->clearEvalCache(); 2781 if (!m_rareData) 2782 return; 2783 m_rareData->m_evalCodeCache.clear(); 2784} 2785 2786template<typename T, size_t inlineCapacity, typename U, typename V> 2787inline void replaceExistingEntries(Vector<T, inlineCapacity, U>& target, Vector<T, inlineCapacity, V>& source) 2788{ 2789 ASSERT(target.size() <= source.size()); 2790 for (size_t i = 0; i < target.size(); ++i) 2791 target[i] = source[i]; 2792} 2793 2794void CodeBlock::copyPostParseDataFrom(CodeBlock* alternative) 2795{ 2796 if (!alternative) 2797 return; 2798 2799 replaceExistingEntries(m_constantRegisters, alternative->m_constantRegisters); 2800 replaceExistingEntries(m_functionDecls, alternative->m_functionDecls); 2801 replaceExistingEntries(m_functionExprs, alternative->m_functionExprs); 2802 if (!!m_rareData && !!alternative->m_rareData) 2803 replaceExistingEntries(m_rareData->m_constantBuffers, alternative->m_rareData->m_constantBuffers); 2804} 2805 2806void CodeBlock::copyPostParseDataFromAlternative() 2807{ 2808 copyPostParseDataFrom(m_alternative.get()); 2809} 2810 2811#if ENABLE(JIT) 2812void CodeBlock::reoptimize() 2813{ 2814 ASSERT(replacement() != this); 2815 ASSERT(replacement()->alternative() == this); 2816 if (DFG::shouldShowDisassembly()) 2817 dataLog(*replacement(), " will be jettisoned due to reoptimization of ", *this, ".\n"); 2818 replacement()->jettison(); 2819 countReoptimization(); 2820} 2821 2822CodeBlock* ProgramCodeBlock::replacement() 2823{ 2824 return &static_cast<ProgramExecutable*>(ownerExecutable())->generatedBytecode(); 2825} 2826 2827CodeBlock* EvalCodeBlock::replacement() 2828{ 2829 return &static_cast<EvalExecutable*>(ownerExecutable())->generatedBytecode(); 2830} 2831 2832CodeBlock* FunctionCodeBlock::replacement() 2833{ 2834 return &static_cast<FunctionExecutable*>(ownerExecutable())->generatedBytecodeFor(m_isConstructor ? CodeForConstruct : CodeForCall); 2835} 2836 2837JSObject* ProgramCodeBlock::compileOptimized(ExecState* exec, JSScope* scope, unsigned bytecodeIndex) 2838{ 2839 if (replacement()->getJITType() == JITCode::nextTierJIT(getJITType())) 2840 return 0; 2841 JSObject* error = static_cast<ProgramExecutable*>(ownerExecutable())->compileOptimized(exec, scope, bytecodeIndex); 2842 return error; 2843} 2844 2845JSObject* EvalCodeBlock::compileOptimized(ExecState* exec, JSScope* scope, unsigned bytecodeIndex) 2846{ 2847 if (replacement()->getJITType() == JITCode::nextTierJIT(getJITType())) 2848 return 0; 2849 JSObject* error = static_cast<EvalExecutable*>(ownerExecutable())->compileOptimized(exec, scope, bytecodeIndex); 2850 return error; 2851} 2852 2853JSObject* FunctionCodeBlock::compileOptimized(ExecState* exec, JSScope* scope, unsigned bytecodeIndex) 2854{ 2855 if (replacement()->getJITType() == JITCode::nextTierJIT(getJITType())) 2856 return 0; 2857 JSObject* error = static_cast<FunctionExecutable*>(ownerExecutable())->compileOptimizedFor(exec, scope, bytecodeIndex, m_isConstructor ? CodeForConstruct : CodeForCall); 2858 return error; 2859} 2860 2861DFG::CapabilityLevel ProgramCodeBlock::canCompileWithDFGInternal() 2862{ 2863 return DFG::canCompileProgram(this); 2864} 2865 2866DFG::CapabilityLevel EvalCodeBlock::canCompileWithDFGInternal() 2867{ 2868 return DFG::canCompileEval(this); 2869} 2870 2871DFG::CapabilityLevel FunctionCodeBlock::canCompileWithDFGInternal() 2872{ 2873 if (m_isConstructor) 2874 return DFG::canCompileFunctionForConstruct(this); 2875 return DFG::canCompileFunctionForCall(this); 2876} 2877 2878void CodeBlock::jettison() 2879{ 2880 ASSERT(JITCode::isOptimizingJIT(getJITType())); 2881 ASSERT(this == replacement()); 2882 alternative()->optimizeAfterWarmUp(); 2883 tallyFrequentExitSites(); 2884 if (DFG::shouldShowDisassembly()) 2885 dataLog("Jettisoning ", *this, ".\n"); 2886 jettisonImpl(); 2887} 2888 2889void ProgramCodeBlock::jettisonImpl() 2890{ 2891 static_cast<ProgramExecutable*>(ownerExecutable())->jettisonOptimizedCode(*vm()); 2892} 2893 2894void EvalCodeBlock::jettisonImpl() 2895{ 2896 static_cast<EvalExecutable*>(ownerExecutable())->jettisonOptimizedCode(*vm()); 2897} 2898 2899void FunctionCodeBlock::jettisonImpl() 2900{ 2901 static_cast<FunctionExecutable*>(ownerExecutable())->jettisonOptimizedCodeFor(*vm(), m_isConstructor ? CodeForConstruct : CodeForCall); 2902} 2903 2904bool ProgramCodeBlock::jitCompileImpl(ExecState* exec) 2905{ 2906 ASSERT(getJITType() == JITCode::InterpreterThunk); 2907 ASSERT(this == replacement()); 2908 return static_cast<ProgramExecutable*>(ownerExecutable())->jitCompile(exec); 2909} 2910 2911bool EvalCodeBlock::jitCompileImpl(ExecState* exec) 2912{ 2913 ASSERT(getJITType() == JITCode::InterpreterThunk); 2914 ASSERT(this == replacement()); 2915 return static_cast<EvalExecutable*>(ownerExecutable())->jitCompile(exec); 2916} 2917 2918bool FunctionCodeBlock::jitCompileImpl(ExecState* exec) 2919{ 2920 ASSERT(getJITType() == JITCode::InterpreterThunk); 2921 ASSERT(this == replacement()); 2922 return static_cast<FunctionExecutable*>(ownerExecutable())->jitCompileFor(exec, m_isConstructor ? CodeForConstruct : CodeForCall); 2923} 2924#endif 2925 2926JSGlobalObject* CodeBlock::globalObjectFor(CodeOrigin codeOrigin) 2927{ 2928 if (!codeOrigin.inlineCallFrame) 2929 return globalObject(); 2930 return jsCast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get())->generatedBytecode().globalObject(); 2931} 2932 2933unsigned CodeBlock::reoptimizationRetryCounter() const 2934{ 2935 ASSERT(m_reoptimizationRetryCounter <= Options::reoptimizationRetryCounterMax()); 2936 return m_reoptimizationRetryCounter; 2937} 2938 2939void CodeBlock::countReoptimization() 2940{ 2941 m_reoptimizationRetryCounter++; 2942 if (m_reoptimizationRetryCounter > Options::reoptimizationRetryCounterMax()) 2943 m_reoptimizationRetryCounter = Options::reoptimizationRetryCounterMax(); 2944} 2945 2946int32_t CodeBlock::codeTypeThresholdMultiplier() const 2947{ 2948 if (codeType() == EvalCode) 2949 return Options::evalThresholdMultiplier(); 2950 2951 return 1; 2952} 2953 2954double CodeBlock::optimizationThresholdScalingFactor() 2955{ 2956 // This expression arises from doing a least-squares fit of 2957 // 2958 // F[x_] =: a * Sqrt[x + b] + Abs[c * x] + d 2959 // 2960 // against the data points: 2961 // 2962 // x F[x_] 2963 // 10 0.9 (smallest reasonable code block) 2964 // 200 1.0 (typical small-ish code block) 2965 // 320 1.2 (something I saw in 3d-cube that I wanted to optimize) 2966 // 1268 5.0 (something I saw in 3d-cube that I didn't want to optimize) 2967 // 4000 5.5 (random large size, used to cause the function to converge to a shallow curve of some sort) 2968 // 10000 6.0 (similar to above) 2969 // 2970 // I achieve the minimization using the following Mathematica code: 2971 // 2972 // MyFunctionTemplate[x_, a_, b_, c_, d_] := a*Sqrt[x + b] + Abs[c*x] + d 2973 // 2974 // samples = {{10, 0.9}, {200, 1}, {320, 1.2}, {1268, 5}, {4000, 5.5}, {10000, 6}} 2975 // 2976 // solution = 2977 // Minimize[Plus @@ ((MyFunctionTemplate[#[[1]], a, b, c, d] - #[[2]])^2 & /@ samples), 2978 // {a, b, c, d}][[2]] 2979 // 2980 // And the code below (to initialize a, b, c, d) is generated by: 2981 // 2982 // Print["const double " <> ToString[#[[1]]] <> " = " <> 2983 // If[#[[2]] < 0.00001, "0.0", ToString[#[[2]]]] <> ";"] & /@ solution 2984 // 2985 // We've long known the following to be true: 2986 // - Small code blocks are cheap to optimize and so we should do it sooner rather 2987 // than later. 2988 // - Large code blocks are expensive to optimize and so we should postpone doing so, 2989 // and sometimes have a large enough threshold that we never optimize them. 2990 // - The difference in cost is not totally linear because (a) just invoking the 2991 // DFG incurs some base cost and (b) for large code blocks there is enough slop 2992 // in the correlation between instruction count and the actual compilation cost 2993 // that for those large blocks, the instruction count should not have a strong 2994 // influence on our threshold. 2995 // 2996 // I knew the goals but I didn't know how to achieve them; so I picked an interesting 2997 // example where the heuristics were right (code block in 3d-cube with instruction 2998 // count 320, which got compiled early as it should have been) and one where they were 2999 // totally wrong (code block in 3d-cube with instruction count 1268, which was expensive 3000 // to compile and didn't run often enough to warrant compilation in my opinion), and 3001 // then threw in additional data points that represented my own guess of what our 3002 // heuristics should do for some round-numbered examples. 3003 // 3004 // The expression to which I decided to fit the data arose because I started with an 3005 // affine function, and then did two things: put the linear part in an Abs to ensure 3006 // that the fit didn't end up choosing a negative value of c (which would result in 3007 // the function turning over and going negative for large x) and I threw in a Sqrt 3008 // term because Sqrt represents my intution that the function should be more sensitive 3009 // to small changes in small values of x, but less sensitive when x gets large. 3010 3011 // Note that the current fit essentially eliminates the linear portion of the 3012 // expression (c == 0.0). 3013 const double a = 0.061504; 3014 const double b = 1.02406; 3015 const double c = 0.0; 3016 const double d = 0.825914; 3017 3018 double instructionCount = this->instructionCount(); 3019 3020 ASSERT(instructionCount); // Make sure this is called only after we have an instruction stream; otherwise it'll just return the value of d, which makes no sense. 3021 3022 double result = d + a * sqrt(instructionCount + b) + c * instructionCount; 3023#if ENABLE(JIT_VERBOSE_OSR) 3024 dataLog(*this, ": instruction count is ", instructionCount, ", scaling execution counter by ", result, " * ", codeTypeThresholdMultiplier(), "\n"); 3025#endif 3026 return result * codeTypeThresholdMultiplier(); 3027} 3028 3029static int32_t clipThreshold(double threshold) 3030{ 3031 if (threshold < 1.0) 3032 return 1; 3033 3034 if (threshold > static_cast<double>(std::numeric_limits<int32_t>::max())) 3035 return std::numeric_limits<int32_t>::max(); 3036 3037 return static_cast<int32_t>(threshold); 3038} 3039 3040int32_t CodeBlock::counterValueForOptimizeAfterWarmUp() 3041{ 3042 return clipThreshold( 3043 Options::thresholdForOptimizeAfterWarmUp() * 3044 optimizationThresholdScalingFactor() * 3045 (1 << reoptimizationRetryCounter())); 3046} 3047 3048int32_t CodeBlock::counterValueForOptimizeAfterLongWarmUp() 3049{ 3050 return clipThreshold( 3051 Options::thresholdForOptimizeAfterLongWarmUp() * 3052 optimizationThresholdScalingFactor() * 3053 (1 << reoptimizationRetryCounter())); 3054} 3055 3056int32_t CodeBlock::counterValueForOptimizeSoon() 3057{ 3058 return clipThreshold( 3059 Options::thresholdForOptimizeSoon() * 3060 optimizationThresholdScalingFactor() * 3061 (1 << reoptimizationRetryCounter())); 3062} 3063 3064bool CodeBlock::checkIfOptimizationThresholdReached() 3065{ 3066 return m_jitExecuteCounter.checkIfThresholdCrossedAndSet(this); 3067} 3068 3069void CodeBlock::optimizeNextInvocation() 3070{ 3071 m_jitExecuteCounter.setNewThreshold(0, this); 3072} 3073 3074void CodeBlock::dontOptimizeAnytimeSoon() 3075{ 3076 m_jitExecuteCounter.deferIndefinitely(); 3077} 3078 3079void CodeBlock::optimizeAfterWarmUp() 3080{ 3081 m_jitExecuteCounter.setNewThreshold(counterValueForOptimizeAfterWarmUp(), this); 3082} 3083 3084void CodeBlock::optimizeAfterLongWarmUp() 3085{ 3086 m_jitExecuteCounter.setNewThreshold(counterValueForOptimizeAfterLongWarmUp(), this); 3087} 3088 3089void CodeBlock::optimizeSoon() 3090{ 3091 m_jitExecuteCounter.setNewThreshold(counterValueForOptimizeSoon(), this); 3092} 3093 3094#if ENABLE(JIT) 3095uint32_t CodeBlock::adjustedExitCountThreshold(uint32_t desiredThreshold) 3096{ 3097 ASSERT(getJITType() == JITCode::DFGJIT); 3098 // Compute this the lame way so we don't saturate. This is called infrequently 3099 // enough that this loop won't hurt us. 3100 unsigned result = desiredThreshold; 3101 for (unsigned n = baselineVersion()->reoptimizationRetryCounter(); n--;) { 3102 unsigned newResult = result << 1; 3103 if (newResult < result) 3104 return std::numeric_limits<uint32_t>::max(); 3105 result = newResult; 3106 } 3107 return result; 3108} 3109 3110uint32_t CodeBlock::exitCountThresholdForReoptimization() 3111{ 3112 return adjustedExitCountThreshold(Options::osrExitCountForReoptimization() * codeTypeThresholdMultiplier()); 3113} 3114 3115uint32_t CodeBlock::exitCountThresholdForReoptimizationFromLoop() 3116{ 3117 return adjustedExitCountThreshold(Options::osrExitCountForReoptimizationFromLoop() * codeTypeThresholdMultiplier()); 3118} 3119 3120bool CodeBlock::shouldReoptimizeNow() 3121{ 3122 return osrExitCounter() >= exitCountThresholdForReoptimization(); 3123} 3124 3125bool CodeBlock::shouldReoptimizeFromLoopNow() 3126{ 3127 return osrExitCounter() >= exitCountThresholdForReoptimizationFromLoop(); 3128} 3129#endif 3130 3131#if ENABLE(VALUE_PROFILER) 3132ArrayProfile* CodeBlock::getArrayProfile(unsigned bytecodeOffset) 3133{ 3134 for (unsigned i = 0; i < m_arrayProfiles.size(); ++i) { 3135 if (m_arrayProfiles[i].bytecodeOffset() == bytecodeOffset) 3136 return &m_arrayProfiles[i]; 3137 } 3138 return 0; 3139} 3140 3141ArrayProfile* CodeBlock::getOrAddArrayProfile(unsigned bytecodeOffset) 3142{ 3143 ArrayProfile* result = getArrayProfile(bytecodeOffset); 3144 if (result) 3145 return result; 3146 return addArrayProfile(bytecodeOffset); 3147} 3148 3149void CodeBlock::updateAllPredictionsAndCountLiveness( 3150 OperationInProgress operation, unsigned& numberOfLiveNonArgumentValueProfiles, unsigned& numberOfSamplesInProfiles) 3151{ 3152 numberOfLiveNonArgumentValueProfiles = 0; 3153 numberOfSamplesInProfiles = 0; // If this divided by ValueProfile::numberOfBuckets equals numberOfValueProfiles() then value profiles are full. 3154 for (unsigned i = 0; i < totalNumberOfValueProfiles(); ++i) { 3155 ValueProfile* profile = getFromAllValueProfiles(i); 3156 unsigned numSamples = profile->totalNumberOfSamples(); 3157 if (numSamples > ValueProfile::numberOfBuckets) 3158 numSamples = ValueProfile::numberOfBuckets; // We don't want profiles that are extremely hot to be given more weight. 3159 numberOfSamplesInProfiles += numSamples; 3160 if (profile->m_bytecodeOffset < 0) { 3161 profile->computeUpdatedPrediction(operation); 3162 continue; 3163 } 3164 if (profile->numberOfSamples() || profile->m_prediction != SpecNone) 3165 numberOfLiveNonArgumentValueProfiles++; 3166 profile->computeUpdatedPrediction(operation); 3167 } 3168 3169#if ENABLE(DFG_JIT) 3170 m_lazyOperandValueProfiles.computeUpdatedPredictions(operation); 3171#endif 3172} 3173 3174void CodeBlock::updateAllValueProfilePredictions(OperationInProgress operation) 3175{ 3176 unsigned ignoredValue1, ignoredValue2; 3177 updateAllPredictionsAndCountLiveness(operation, ignoredValue1, ignoredValue2); 3178} 3179 3180void CodeBlock::updateAllArrayPredictions(OperationInProgress operation) 3181{ 3182 for (unsigned i = m_arrayProfiles.size(); i--;) 3183 m_arrayProfiles[i].computeUpdatedPrediction(this, operation); 3184 3185 // Don't count these either, for similar reasons. 3186 for (unsigned i = m_arrayAllocationProfiles.size(); i--;) 3187 m_arrayAllocationProfiles[i].updateIndexingType(); 3188} 3189 3190void CodeBlock::updateAllPredictions(OperationInProgress operation) 3191{ 3192 updateAllValueProfilePredictions(operation); 3193 updateAllArrayPredictions(operation); 3194} 3195 3196bool CodeBlock::shouldOptimizeNow() 3197{ 3198#if ENABLE(JIT_VERBOSE_OSR) 3199 dataLog("Considering optimizing ", *this, "...\n"); 3200#endif 3201 3202#if ENABLE(VERBOSE_VALUE_PROFILE) 3203 dumpValueProfiles(); 3204#endif 3205 3206 if (m_optimizationDelayCounter >= Options::maximumOptimizationDelay()) 3207 return true; 3208 3209 updateAllArrayPredictions(); 3210 3211 unsigned numberOfLiveNonArgumentValueProfiles; 3212 unsigned numberOfSamplesInProfiles; 3213 updateAllPredictionsAndCountLiveness(NoOperation, numberOfLiveNonArgumentValueProfiles, numberOfSamplesInProfiles); 3214 3215#if ENABLE(JIT_VERBOSE_OSR) 3216 dataLogF("Profile hotness: %lf (%u / %u), %lf (%u / %u)\n", (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles(), numberOfLiveNonArgumentValueProfiles, numberOfValueProfiles(), (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles(), numberOfSamplesInProfiles, ValueProfile::numberOfBuckets * numberOfValueProfiles()); 3217#endif 3218 3219 if ((!numberOfValueProfiles() || (double)numberOfLiveNonArgumentValueProfiles / numberOfValueProfiles() >= Options::desiredProfileLivenessRate()) 3220 && (!totalNumberOfValueProfiles() || (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / totalNumberOfValueProfiles() >= Options::desiredProfileFullnessRate()) 3221 && static_cast<unsigned>(m_optimizationDelayCounter) + 1 >= Options::minimumOptimizationDelay()) 3222 return true; 3223 3224 ASSERT(m_optimizationDelayCounter < std::numeric_limits<uint8_t>::max()); 3225 m_optimizationDelayCounter++; 3226 optimizeAfterWarmUp(); 3227 return false; 3228} 3229#endif 3230 3231#if ENABLE(DFG_JIT) 3232void CodeBlock::tallyFrequentExitSites() 3233{ 3234 ASSERT(getJITType() == JITCode::DFGJIT); 3235 ASSERT(alternative()->getJITType() == JITCode::BaselineJIT); 3236 ASSERT(!!m_dfgData); 3237 3238 CodeBlock* profiledBlock = alternative(); 3239 3240 for (unsigned i = 0; i < m_dfgData->osrExit.size(); ++i) { 3241 DFG::OSRExit& exit = m_dfgData->osrExit[i]; 3242 3243 if (!exit.considerAddingAsFrequentExitSite(profiledBlock)) 3244 continue; 3245 3246#if DFG_ENABLE(DEBUG_VERBOSE) 3247 dataLog("OSR exit #", i, " (bc#", exit.m_codeOrigin.bytecodeIndex, ", ", exit.m_kind, ") for ", *this, " occurred frequently: counting as frequent exit site.\n"); 3248#endif 3249 } 3250} 3251#endif // ENABLE(DFG_JIT) 3252 3253#if ENABLE(VERBOSE_VALUE_PROFILE) 3254void CodeBlock::dumpValueProfiles() 3255{ 3256 dataLog("ValueProfile for ", *this, ":\n"); 3257 for (unsigned i = 0; i < totalNumberOfValueProfiles(); ++i) { 3258 ValueProfile* profile = getFromAllValueProfiles(i); 3259 if (profile->m_bytecodeOffset < 0) { 3260 ASSERT(profile->m_bytecodeOffset == -1); 3261 dataLogF(" arg = %u: ", i); 3262 } else 3263 dataLogF(" bc = %d: ", profile->m_bytecodeOffset); 3264 if (!profile->numberOfSamples() && profile->m_prediction == SpecNone) { 3265 dataLogF("<empty>\n"); 3266 continue; 3267 } 3268 profile->dump(WTF::dataFile()); 3269 dataLogF("\n"); 3270 } 3271 dataLog("RareCaseProfile for ", *this, ":\n"); 3272 for (unsigned i = 0; i < numberOfRareCaseProfiles(); ++i) { 3273 RareCaseProfile* profile = rareCaseProfile(i); 3274 dataLogF(" bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter); 3275 } 3276 dataLog("SpecialFastCaseProfile for ", *this, ":\n"); 3277 for (unsigned i = 0; i < numberOfSpecialFastCaseProfiles(); ++i) { 3278 RareCaseProfile* profile = specialFastCaseProfile(i); 3279 dataLogF(" bc = %d: %u\n", profile->m_bytecodeOffset, profile->m_counter); 3280 } 3281} 3282#endif // ENABLE(VERBOSE_VALUE_PROFILE) 3283 3284size_t CodeBlock::predictedMachineCodeSize() 3285{ 3286 // This will be called from CodeBlock::CodeBlock before either m_vm or the 3287 // instructions have been initialized. It's OK to return 0 because what will really 3288 // matter is the recomputation of this value when the slow path is triggered. 3289 if (!m_vm) 3290 return 0; 3291 3292 if (!m_vm->machineCodeBytesPerBytecodeWordForBaselineJIT) 3293 return 0; // It's as good of a prediction as we'll get. 3294 3295 // Be conservative: return a size that will be an overestimation 84% of the time. 3296 double multiplier = m_vm->machineCodeBytesPerBytecodeWordForBaselineJIT.mean() + 3297 m_vm->machineCodeBytesPerBytecodeWordForBaselineJIT.standardDeviation(); 3298 3299 // Be paranoid: silently reject bogus multipiers. Silently doing the "wrong" thing 3300 // here is OK, since this whole method is just a heuristic. 3301 if (multiplier < 0 || multiplier > 1000) 3302 return 0; 3303 3304 double doubleResult = multiplier * m_instructions.size(); 3305 3306 // Be even more paranoid: silently reject values that won't fit into a size_t. If 3307 // the function is so huge that we can't even fit it into virtual memory then we 3308 // should probably have some other guards in place to prevent us from even getting 3309 // to this point. 3310 if (doubleResult > std::numeric_limits<size_t>::max()) 3311 return 0; 3312 3313 return static_cast<size_t>(doubleResult); 3314} 3315 3316bool CodeBlock::usesOpcode(OpcodeID opcodeID) 3317{ 3318 Interpreter* interpreter = vm()->interpreter; 3319 Instruction* instructionsBegin = instructions().begin(); 3320 unsigned instructionCount = instructions().size(); 3321 3322 for (unsigned bytecodeOffset = 0; bytecodeOffset < instructionCount; ) { 3323 switch (interpreter->getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode)) { 3324#define DEFINE_OP(curOpcode, length) \ 3325 case curOpcode: \ 3326 if (curOpcode == opcodeID) \ 3327 return true; \ 3328 bytecodeOffset += length; \ 3329 break; 3330 FOR_EACH_OPCODE_ID(DEFINE_OP) 3331#undef DEFINE_OP 3332 default: 3333 RELEASE_ASSERT_NOT_REACHED(); 3334 break; 3335 } 3336 } 3337 3338 return false; 3339} 3340 3341String CodeBlock::nameForRegister(int registerNumber) 3342{ 3343 SymbolTable::iterator end = symbolTable()->end(); 3344 for (SymbolTable::iterator ptr = symbolTable()->begin(); ptr != end; ++ptr) { 3345 if (ptr->value.getIndex() == registerNumber) 3346 return String(ptr->key); 3347 } 3348 if (needsActivation() && registerNumber == activationRegister()) 3349 return ASCIILiteral("activation"); 3350 if (registerNumber == thisRegister()) 3351 return ASCIILiteral("this"); 3352 if (usesArguments()) { 3353 if (registerNumber == argumentsRegister()) 3354 return ASCIILiteral("arguments"); 3355 if (unmodifiedArgumentsRegister(argumentsRegister()) == registerNumber) 3356 return ASCIILiteral("real arguments"); 3357 } 3358 if (registerNumber < 0) { 3359 int argumentPosition = -registerNumber; 3360 argumentPosition -= JSStack::CallFrameHeaderSize + 1; 3361 return String::format("arguments[%3d]", argumentPosition - 1).impl(); 3362 } 3363 return ""; 3364} 3365 3366} // namespace JSC 3367