+String CodeBlock::nameForRegister(VirtualRegister virtualRegister)
+{
+ ConcurrentJITLocker locker(symbolTable()->m_lock);
+ SymbolTable::Map::iterator end = symbolTable()->end(locker);
+ for (SymbolTable::Map::iterator ptr = symbolTable()->begin(locker); ptr != end; ++ptr) {
+ if (ptr->value.getIndex() == virtualRegister.offset()) {
+ // FIXME: This won't work from the compilation thread.
+ // https://bugs.webkit.org/show_bug.cgi?id=115300
+ return String(ptr->key);
+ }
+ }
+ if (needsActivation() && virtualRegister == activationRegister())
+ return ASCIILiteral("activation");
+ if (virtualRegister == thisRegister())
+ return ASCIILiteral("this");
+ if (usesArguments()) {
+ if (virtualRegister == argumentsRegister())
+ return ASCIILiteral("arguments");
+ if (unmodifiedArgumentsRegister(argumentsRegister()) == virtualRegister)
+ return ASCIILiteral("real arguments");
+ }
+ if (virtualRegister.isArgument())
+ return String::format("arguments[%3d]", virtualRegister.toArgument()).impl();
+
+ return "";
+}
+
+namespace {
+
+struct VerifyCapturedDef {
+ void operator()(CodeBlock* codeBlock, Instruction* instruction, OpcodeID opcodeID, int operand)
+ {
+ unsigned bytecodeOffset = instruction - codeBlock->instructions().begin();
+
+ if (codeBlock->isConstantRegisterIndex(operand)) {
+ codeBlock->beginValidationDidFail();
+ dataLog(" At bc#", bytecodeOffset, " encountered a definition of a constant.\n");
+ codeBlock->endValidationDidFail();
+ return;
+ }
+
+ switch (opcodeID) {
+ case op_enter:
+ case op_captured_mov:
+ case op_init_lazy_reg:
+ case op_create_arguments:
+ case op_new_captured_func:
+ return;
+ default:
+ break;
+ }
+
+ VirtualRegister virtualReg(operand);
+ if (!virtualReg.isLocal())
+ return;
+
+ if (codeBlock->captureCount() && codeBlock->symbolTable()->isCaptured(operand)) {
+ codeBlock->beginValidationDidFail();
+ dataLog(" At bc#", bytecodeOffset, " encountered invalid assignment to captured variable loc", virtualReg.toLocal(), ".\n");
+ codeBlock->endValidationDidFail();
+ return;
+ }
+
+ return;
+ }
+};
+
+} // anonymous namespace
+
+void CodeBlock::validate()
+{
+ BytecodeLivenessAnalysis liveness(this); // Compute directly from scratch so it doesn't effect CodeBlock footprint.
+
+ FastBitVector liveAtHead = liveness.getLivenessInfoAtBytecodeOffset(0);
+
+ if (liveAtHead.numBits() != static_cast<size_t>(m_numCalleeRegisters)) {
+ beginValidationDidFail();
+ dataLog(" Wrong number of bits in result!\n");
+ dataLog(" Result: ", liveAtHead, "\n");
+ dataLog(" Bit count: ", liveAtHead.numBits(), "\n");
+ endValidationDidFail();
+ }
+
+ for (unsigned i = m_numCalleeRegisters; i--;) {
+ bool isCaptured = false;
+ VirtualRegister reg = virtualRegisterForLocal(i);
+
+ if (captureCount())
+ isCaptured = reg.offset() <= captureStart() && reg.offset() > captureEnd();
+
+ if (isCaptured) {
+ if (!liveAtHead.get(i)) {
+ beginValidationDidFail();
+ dataLog(" Variable loc", i, " is expected to be live because it is captured, but it isn't live.\n");
+ dataLog(" Result: ", liveAtHead, "\n");
+ endValidationDidFail();
+ }
+ } else {
+ if (liveAtHead.get(i)) {
+ beginValidationDidFail();
+ dataLog(" Variable loc", i, " is expected to be dead.\n");
+ dataLog(" Result: ", liveAtHead, "\n");
+ endValidationDidFail();
+ }
+ }
+ }
+
+ for (unsigned bytecodeOffset = 0; bytecodeOffset < instructions().size();) {
+ Instruction* currentInstruction = instructions().begin() + bytecodeOffset;
+ OpcodeID opcodeID = m_vm->interpreter->getOpcodeID(currentInstruction->u.opcode);
+
+ VerifyCapturedDef verifyCapturedDef;
+ computeDefsForBytecodeOffset(this, bytecodeOffset, verifyCapturedDef);
+
+ bytecodeOffset += opcodeLength(opcodeID);
+ }
+}
+
+void CodeBlock::beginValidationDidFail()
+{
+ dataLog("Validation failure in ", *this, ":\n");
+ dataLog("\n");
+}
+
+void CodeBlock::endValidationDidFail()
+{
+ dataLog("\n");
+ dumpBytecode();
+ dataLog("\n");
+ dataLog("Validation failure.\n");
+ RELEASE_ASSERT_NOT_REACHED();
+}
+
+void CodeBlock::addBreakpoint(unsigned numBreakpoints)
+{
+ m_numBreakpoints += numBreakpoints;
+ ASSERT(m_numBreakpoints);
+ if (JITCode::isOptimizingJIT(jitType()))
+ jettison(Profiler::JettisonDueToDebuggerBreakpoint);
+}
+
+void CodeBlock::setSteppingMode(CodeBlock::SteppingMode mode)
+{
+ m_steppingMode = mode;
+ if (mode == SteppingModeEnabled && JITCode::isOptimizingJIT(jitType()))
+ jettison(Profiler::JettisonDueToDebuggerStepping);
+}
+
+RareCaseProfile* CodeBlock::rareCaseProfileForBytecodeOffset(int bytecodeOffset)
+{
+ return tryBinarySearch<RareCaseProfile, int>(
+ m_rareCaseProfiles, m_rareCaseProfiles.size(), bytecodeOffset,
+ getRareCaseProfileBytecodeOffset);
+}
+
+#if ENABLE(JIT)
+DFG::CapabilityLevel CodeBlock::capabilityLevel()
+{
+ DFG::CapabilityLevel result = capabilityLevelInternal();
+ m_capabilityLevelState = result;
+ return result;
+}
+#endif
+