void Disassembler::dumpHeader(PrintStream& out, LinkBuffer& linkBuffer) { out.print("Generated DFG JIT code for ", CodeBlockWithJITType(m_graph.m_codeBlock, JITCode::DFGJIT), ", instruction count = ", m_graph.m_codeBlock->instructionCount(), ":\n"); out.print(" Optimized with execution counter = ", m_graph.m_profiledBlock->jitExecuteCounter(), "\n"); out.print(" Source: ", m_graph.m_codeBlock->sourceCodeOnOneLine(), "\n"); out.print(" Code at [", RawPointer(linkBuffer.debugAddress()), ", ", RawPointer(static_cast<char*>(linkBuffer.debugAddress()) + linkBuffer.debugSize()), "):\n"); }
void CallLinkInfo::visitWeak(RepatchBuffer& repatchBuffer) { if (isLinked()) { if (stub) { if (!Heap::isMarked(stub->executable())) { if (Options::verboseOSR()) { dataLog( "Clearing closure call from ", *repatchBuffer.codeBlock(), " to ", stub->executable()->hashFor(specializationKind()), ", stub routine ", RawPointer(stub.get()), ".\n"); } unlink(repatchBuffer); } } else if (!Heap::isMarked(callee.get())) { if (Options::verboseOSR()) { dataLog( "Clearing call from ", *repatchBuffer.codeBlock(), " to ", RawPointer(callee.get()), " (", callee.get()->executable()->hashFor(specializationKind()), ").\n"); } unlink(repatchBuffer); } } if (!!lastSeenCallee && !Heap::isMarked(lastSeenCallee.get())) lastSeenCallee.clear(); }
void CallLinkStatus::dump(PrintStream& out) const { if (!isSet()) { out.print("Not Set"); return; } CommaPrinter comma; if (m_isProved) out.print(comma, "Statically Proved"); if (m_couldTakeSlowPath) out.print(comma, "Could Take Slow Path"); if (m_callTarget) out.print(comma, "Known target: ", m_callTarget); if (m_executable) { out.print(comma, "Executable/CallHash: ", RawPointer(m_executable)); if (!isCompilationThread()) out.print("/", m_executable->hashFor(CodeForCall)); } if (m_structure) out.print(comma, "Structure: ", RawPointer(m_structure)); }
void GetterSetterAccessCase::dumpImpl(PrintStream& out, CommaPrinter& comma) const { Base::dumpImpl(out, comma); out.print(comma, "customSlotBase = ", RawPointer(customSlotBase())); if (callLinkInfo()) out.print(comma, "callLinkInfo = ", RawPointer(callLinkInfo())); out.print(comma, "customAccessor = ", RawPointer(m_customAccessor.opaque)); }
void AutomaticThread::start(const LockHolder&) { RELEASE_ASSERT(m_isRunning); RefPtr<AutomaticThread> preserveThisForThread = this; m_hasUnderlyingThread = true; ThreadIdentifier thread = createThread( "WTF::AutomaticThread", [=] () { if (verbose) dataLog(RawPointer(this), ": Running automatic thread!\n"); ThreadScope threadScope(preserveThisForThread); if (!ASSERT_DISABLED) { LockHolder locker(*m_lock); ASSERT(!m_condition->contains(locker, this)); } auto stop = [&] (const LockHolder&) { m_isRunning = false; m_isRunningCondition.notifyAll(); }; for (;;) { { LockHolder locker(*m_lock); for (;;) { PollResult result = poll(locker); if (result == PollResult::Work) break; if (result == PollResult::Stop) return stop(locker); RELEASE_ASSERT(result == PollResult::Wait); // Shut the thread down after one second. bool awokenByNotify = m_condition->m_condition.waitFor(*m_lock, 1_s); if (!awokenByNotify) { if (verbose) dataLog(RawPointer(this), ": Going to sleep!\n"); m_condition->add(locker, this); return; } } } WorkResult result = work(); if (result == WorkResult::Stop) { LockHolder locker(*m_lock); return stop(locker); } RELEASE_ASSERT(result == WorkResult::Continue); } }); detachThread(thread); }
void logSanitizeStack(VM* vm) { if (Options::verboseSanitizeStack() && vm->topCallFrame) { int dummy; dataLog( "Sanitizing stack with top call frame at ", RawPointer(vm->topCallFrame), ", current stack pointer at ", RawPointer(&dummy), ", in ", pointerDump(vm->topCallFrame->codeBlock()), " and last code origin = ", vm->topCallFrame->codeOrigin(), "\n"); } }
void MacroAssemblerCodePtr::dumpWithName(const char* name, PrintStream& out) const { if (!m_value) { out.print(name, "(null)"); return; } if (executableAddress() == dataLocation()) { out.print(name, "(", RawPointer(executableAddress()), ")"); return; } out.print(name, "(executable = ", RawPointer(executableAddress()), ", dataLocation = ", RawPointer(dataLocation()), ")"); }
void genericUnwind(VM* vm, ExecState* callFrame, UnwindStart unwindStart) { if (Options::breakOnThrow()) { CodeBlock* codeBlock = callFrame->codeBlock(); if (codeBlock) dataLog("In call frame ", RawPointer(callFrame), " for code block ", *codeBlock, "\n"); else dataLog("In call frame ", RawPointer(callFrame), " with null CodeBlock\n"); CRASH(); } ExecState* shadowChickenTopFrame = callFrame; if (unwindStart == UnwindFromCallerFrame) { VMEntryFrame* topVMEntryFrame = vm->topVMEntryFrame; shadowChickenTopFrame = callFrame->callerFrame(topVMEntryFrame); } vm->shadowChicken().log(*vm, shadowChickenTopFrame, ShadowChicken::Packet::throwPacket()); Exception* exception = vm->exception(); RELEASE_ASSERT(exception); HandlerInfo* handler = vm->interpreter->unwind(*vm, callFrame, exception, unwindStart); // This may update callFrame. void* catchRoutine; Instruction* catchPCForInterpreter = 0; if (handler) { // handler->target is meaningless for getting a code offset when catching // the exception in a DFG/FTL frame. This bytecode target offset could be // something that's in an inlined frame, which means an array access // with this bytecode offset in the machine frame is utterly meaningless // and can cause an overflow. OSR exit properly exits to handler->target // in the proper frame. if (!JITCode::isOptimizingJIT(callFrame->codeBlock()->jitType())) catchPCForInterpreter = &callFrame->codeBlock()->instructions()[handler->target]; #if ENABLE(JIT) catchRoutine = handler->nativeCode.executableAddress(); #else catchRoutine = catchPCForInterpreter->u.pointer; #endif } else catchRoutine = LLInt::getCodePtr(handleUncaughtException); ASSERT(bitwise_cast<uintptr_t>(callFrame) < bitwise_cast<uintptr_t>(vm->topVMEntryFrame)); vm->callFrameForCatch = callFrame; vm->targetMachinePCForThrow = catchRoutine; vm->targetInterpreterPCForThrow = catchPCForInterpreter; RELEASE_ASSERT(catchRoutine); }
ObjectPropertyConditionSet generateConditionsForInstanceOf( VM& vm, JSCell* owner, ExecState* exec, Structure* headStructure, JSObject* prototype, bool shouldHit) { bool didHit = false; if (ObjectPropertyConditionSetInternal::verbose) dataLog("Searching for prototype ", JSValue(prototype), " starting with structure ", RawPointer(headStructure), " with shouldHit = ", shouldHit, "\n"); ObjectPropertyConditionSet result = generateConditions( vm, exec->lexicalGlobalObject(), headStructure, shouldHit ? prototype : nullptr, [&] (Vector<ObjectPropertyCondition>& conditions, JSObject* object) -> bool { if (ObjectPropertyConditionSetInternal::verbose) dataLog("Encountered object: ", RawPointer(object), "\n"); if (object == prototype) { RELEASE_ASSERT(shouldHit); didHit = true; return true; } Structure* structure = object->structure(vm); if (structure->hasPolyProto()) return false; conditions.append( ObjectPropertyCondition::hasPrototype( vm, owner, object, structure->storedPrototypeObject())); return true; }); if (result.isValid()) { if (ObjectPropertyConditionSetInternal::verbose) dataLog("didHit = ", didHit, ", shouldHit = ", shouldHit, "\n"); RELEASE_ASSERT(didHit == shouldHit); } return result; }
static CodeBlock* codeBlockFromArg(ExecState* exec) { VM& vm = exec->vm(); if (exec->argumentCount() < 1) return nullptr; JSValue value = exec->uncheckedArgument(0); CodeBlock* candidateCodeBlock = nullptr; if (value.isCell()) { JSFunction* func = jsDynamicCast<JSFunction*>(vm, value.asCell()); if (func) { if (func->isHostFunction()) candidateCodeBlock = nullptr; else candidateCodeBlock = func->jsExecutable()->eitherCodeBlock(); } } else if (value.isDouble()) { // If the value is a double, it may be an encoded CodeBlock* that came from // $vm.codeBlockForFrame(). We'll treat it as a candidate codeBlock and check if it's // valid below before using. candidateCodeBlock = reinterpret_cast<CodeBlock*>(bitwise_cast<uint64_t>(value.asDouble())); } if (candidateCodeBlock && JSDollarVMPrototype::isValidCodeBlock(exec, candidateCodeBlock)) return candidateCodeBlock; if (candidateCodeBlock) dataLog("Invalid codeBlock: ", RawPointer(candidateCodeBlock), " ", value, "\n"); else dataLog("Invalid codeBlock: ", value, "\n"); return nullptr; }
void AdaptiveInferredPropertyValueWatchpoint::fire(const FireDetail& detail) { // One of the watchpoints fired, but the other one didn't. Make sure that neither of them are // in any set anymore. This simplifies things by allowing us to reinstall the watchpoints // wherever from scratch. if (m_structureWatchpoint.isOnList()) m_structureWatchpoint.remove(); if (m_propertyWatchpoint.isOnList()) m_propertyWatchpoint.remove(); if (m_key.isWatchable(PropertyCondition::EnsureWatchability)) { install(); return; } if (DFG::shouldShowDisassembly()) { dataLog( "Firing watchpoint ", RawPointer(this), " (", m_key, ") on ", *m_codeBlock, "\n"); } StringPrintStream out; out.print("Adaptation of ", m_key, " failed: ", detail); StringFireDetail stringDetail(out.toCString().data()); m_codeBlock->jettison( Profiler::JettisonDueToUnprofiledWatchpoint, CountReoptimization, &stringDetail); }
void Worklist::dump(const MutexLocker&, PrintStream& out) const { out.print( "Worklist(", RawPointer(this), ")[Queue Length = ", m_queue.size(), ", Map Size = ", m_plans.size(), ", Num Ready = ", m_readyPlans.size(), ", Num Active Threads = ", m_numberOfActiveThreads, "/", m_threads.size(), "]"); }
void HeapSnapshot::finalize() { ASSERT(!m_finalized); m_finalized = true; // Nodes are appended to the snapshot in identifier order. // Now that we have the complete list of nodes we will sort // them in a different order. Remember the range of identifiers // in this snapshot. if (!isEmpty()) { m_firstObjectIdentifier = m_nodes.first().identifier; m_lastObjectIdentifier = m_nodes.last().identifier; } std::sort(m_nodes.begin(), m_nodes.end(), [] (const HeapSnapshotNode& a, const HeapSnapshotNode& b) { return a.cell < b.cell; }); #ifndef NDEBUG // Assert there are no duplicates or nullptr cells. JSCell* previousCell = nullptr; for (auto& node : m_nodes) { ASSERT(node.cell); ASSERT(!(reinterpret_cast<intptr_t>(node.cell) & CellToSweepTag)); if (node.cell == previousCell) { dataLog("Seeing same cell twice: ", RawPointer(previousCell), "\n"); ASSERT(node.cell != previousCell); } previousCell = node.cell; } #endif }
void CodeBlockJettisoningWatchpoint::fireInternal(VM&, const FireDetail& detail) { if (DFG::shouldDumpDisassembly()) dataLog("Firing watchpoint ", RawPointer(this), " on ", *m_codeBlock, "\n"); m_codeBlock->jettison(Profiler::JettisonDueToUnprofiledWatchpoint, CountReoptimization, &detail); }
void genericUnwind(VM* vm, ExecState* callFrame, JSValue exceptionValue) { if (Options::breakOnThrow()) { dataLog("In call frame ", RawPointer(callFrame), " for code block ", *callFrame->codeBlock(), "\n"); CRASH(); } RELEASE_ASSERT(exceptionValue); VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame; HandlerInfo* handler = vm->interpreter->unwind(vmEntryFrame, callFrame, exceptionValue); // This may update vmEntryFrame and callFrame. void* catchRoutine; Instruction* catchPCForInterpreter = 0; if (handler) { catchPCForInterpreter = &callFrame->codeBlock()->instructions()[handler->target]; #if ENABLE(JIT) catchRoutine = handler->nativeCode.executableAddress(); #else catchRoutine = catchPCForInterpreter->u.pointer; #endif } else catchRoutine = LLInt::getCodePtr(handleUncaughtException); vm->vmEntryFrameForThrow = vmEntryFrame; vm->callFrameForThrow = callFrame; vm->targetMachinePCForThrow = catchRoutine; vm->targetInterpreterPCForThrow = catchPCForInterpreter; RELEASE_ASSERT(catchRoutine); }
CString ArrayProfile::briefDescription(CodeBlock* codeBlock) { computeUpdatedPrediction(codeBlock); StringPrintStream out; bool hasPrinted = false; if (m_observedArrayModes) { if (hasPrinted) out.print(", "); out.print(ArrayModesDump(m_observedArrayModes)); hasPrinted = true; } if (structureIsPolymorphic()) { if (hasPrinted) out.print(", "); out.print("struct = TOP"); hasPrinted = true; } else if (m_expectedStructure) { if (hasPrinted) out.print(", "); out.print("struct = ", RawPointer(m_expectedStructure)); hasPrinted = true; } if (m_mayStoreToHole) { if (hasPrinted) out.print(", "); out.print("Hole"); hasPrinted = true; } if (m_outOfBounds) { if (hasPrinted) out.print(", "); out.print("OutOfBounds"); hasPrinted = true; } if (m_mayInterceptIndexedAccesses) { if (hasPrinted) out.print(", "); out.print("Intercept"); hasPrinted = true; } if (m_usesOriginalArrayStructures) { if (hasPrinted) out.print(", "); out.print("Original"); hasPrinted = true; } UNUSED_PARAM(hasPrinted); return out.toCString(); }
AutomaticThread::AutomaticThread(const LockHolder& locker, Box<Lock> lock, RefPtr<AutomaticThreadCondition> condition) : m_lock(lock) , m_condition(condition) { if (verbose) dataLog(RawPointer(this), ": Allocated AutomaticThread.\n"); m_condition->add(locker, this); }
void Disassembler::dump(PrintStream& out, LinkBuffer& linkBuffer) { m_graph.m_dominators.computeIfNecessary(m_graph); out.print("Generated DFG JIT code for ", CodeBlockWithJITType(m_graph.m_codeBlock, JITCode::DFGJIT), ", instruction count = ", m_graph.m_codeBlock->instructionCount(), ":\n"); out.print(" Code at [", RawPointer(linkBuffer.debugAddress()), ", ", RawPointer(static_cast<char*>(linkBuffer.debugAddress()) + linkBuffer.debugSize()), "):\n"); const char* prefix = " "; const char* disassemblyPrefix = " "; NodeIndex lastNodeIndex = NoNode; MacroAssembler::Label previousLabel = m_startOfCode; for (size_t blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) { BasicBlock* block = m_graph.m_blocks[blockIndex].get(); if (!block) continue; dumpDisassembly(out, disassemblyPrefix, linkBuffer, previousLabel, m_labelForBlockIndex[blockIndex], lastNodeIndex); m_graph.dumpBlockHeader(out, prefix, blockIndex, Graph::DumpLivePhisOnly); NodeIndex lastNodeIndexForDisassembly = block->at(0); for (size_t i = 0; i < block->size(); ++i) { if (!m_graph[block->at(i)].willHaveCodeGenOrOSR() && !Options::showAllDFGNodes()) continue; MacroAssembler::Label currentLabel; if (m_labelForNodeIndex[block->at(i)].isSet()) currentLabel = m_labelForNodeIndex[block->at(i)]; else { // Dump the last instruction by using the first label of the next block // as the end point. This case is hit either during peephole compare // optimizations (the Branch won't have its own label) or if we have a // forced OSR exit. if (blockIndex + 1 < m_graph.m_blocks.size()) currentLabel = m_labelForBlockIndex[blockIndex + 1]; else currentLabel = m_endOfMainPath; } dumpDisassembly(out, disassemblyPrefix, linkBuffer, previousLabel, currentLabel, lastNodeIndexForDisassembly); m_graph.dumpCodeOrigin(out, prefix, lastNodeIndex, block->at(i)); m_graph.dump(out, prefix, block->at(i)); lastNodeIndex = block->at(i); lastNodeIndexForDisassembly = block->at(i); } } dumpDisassembly(out, disassemblyPrefix, linkBuffer, previousLabel, m_endOfMainPath, lastNodeIndex); out.print(prefix, "(End Of Main Path)\n"); dumpDisassembly(out, disassemblyPrefix, linkBuffer, previousLabel, m_endOfCode, NoNode); }
void BlockDirectory::stopAllocating() { if (false) dataLog(RawPointer(this), ": BlockDirectory::stopAllocating!\n"); m_localAllocators.forEach( [&] (LocalAllocator* allocator) { allocator->stopAllocating(); }); }
void* prepareOSREntry( ExecState* exec, CodeBlock* dfgCodeBlock, CodeBlock* entryCodeBlock, unsigned bytecodeIndex, unsigned streamIndex) { VM& vm = exec->vm(); CodeBlock* baseline = dfgCodeBlock->baselineVersion(); DFG::JITCode* dfgCode = dfgCodeBlock->jitCode()->dfg(); ForOSREntryJITCode* entryCode = entryCodeBlock->jitCode()->ftlForOSREntry(); if (Options::verboseOSR()) { dataLog( "FTL OSR from ", *dfgCodeBlock, " to ", *entryCodeBlock, " at bc#", bytecodeIndex, ".\n"); } if (bytecodeIndex != entryCode->bytecodeIndex()) { if (Options::verboseOSR()) dataLog(" OSR failed because we don't have an entrypoint for bc#", bytecodeIndex, "; ours is for bc#", entryCode->bytecodeIndex()); return 0; } Operands<JSValue> values; dfgCode->reconstruct( exec, dfgCodeBlock, CodeOrigin(bytecodeIndex), streamIndex, values); if (Options::verboseOSR()) dataLog(" Values at entry: ", values, "\n"); for (int argument = values.numberOfArguments(); argument--;) { RELEASE_ASSERT( exec->r(virtualRegisterForArgument(argument).offset()).jsValue() == values.argument(argument)); } RELEASE_ASSERT( static_cast<int>(values.numberOfLocals()) == baseline->m_numCalleeRegisters); EncodedJSValue* scratch = static_cast<EncodedJSValue*>( entryCode->entryBuffer()->dataBuffer()); for (int local = values.numberOfLocals(); local--;) scratch[local] = JSValue::encode(values.local(local)); int stackFrameSize = entryCode->common.requiredRegisterCountForExecutionAndExit(); if (!vm.interpreter->stack().grow(&exec->registers()[virtualRegisterForLocal(stackFrameSize).offset()])) { if (Options::verboseOSR()) dataLog(" OSR failed because stack growth failed.\n"); return 0; } exec->setCodeBlock(entryCodeBlock); void* result = entryCode->addressForCall().executableAddress(); if (Options::verboseOSR()) dataLog(" Entry will succeed, going to address", RawPointer(result), "\n"); return result; }
void Plan::run() { if (verbose) dataLogLn("Starting plan."); { ModuleParser moduleParser(m_source, m_sourceLength); if (!moduleParser.parse()) { if (verbose) dataLogLn("Parsing module failed: ", moduleParser.errorMessage()); m_errorMessage = moduleParser.errorMessage(); return; } m_moduleInformation = WTFMove(moduleParser.moduleInformation()); } if (verbose) dataLogLn("Parsed module."); if (!m_compiledFunctions.tryReserveCapacity(m_moduleInformation->functions.size())) { StringBuilder builder; builder.appendLiteral("Failed allocating enough space for "); builder.appendNumber(m_moduleInformation->functions.size()); builder.appendLiteral(" compiled functions"); m_errorMessage = builder.toString(); return; } for (const FunctionInformation& info : m_moduleInformation->functions) { if (verbose) dataLogLn("Processing function starting at: ", info.start, " and ending at: ", info.end); const uint8_t* functionStart = m_source + info.start; size_t functionLength = info.end - info.start; ASSERT(functionLength <= m_sourceLength); String error = validateFunction(functionStart, functionLength, info.signature, m_moduleInformation->functions); if (!error.isNull()) { if (verbose) { for (unsigned i = 0; i < functionLength; ++i) dataLog(RawPointer(reinterpret_cast<void*>(functionStart[i])), ", "); dataLogLn(); } m_errorMessage = error; return; } m_compiledFunctions.uncheckedAppend(parseAndCompile(*m_vm, functionStart, functionLength, m_moduleInformation->memory.get(), info.signature, m_moduleInformation->functions)); } // Patch the call sites for each function. for (std::unique_ptr<FunctionCompilation>& functionPtr : m_compiledFunctions) { FunctionCompilation* function = functionPtr.get(); for (auto& call : function->unlinkedCalls) MacroAssembler::repatchCall(call.callLocation, CodeLocationLabel(m_compiledFunctions[call.functionIndex]->code->code())); } m_failed = false; }
JSValue OSRExitSite::toJS(ExecState* exec) const { VM& vm = exec->vm(); auto scope = DECLARE_THROW_SCOPE(vm); JSArray* result = constructEmptyArray(exec, 0); RETURN_IF_EXCEPTION(scope, JSValue()); for (unsigned i = 0; i < m_codeAddresses.size(); ++i) result->putDirectIndex(exec, i, jsString(exec, toString(RawPointer(m_codeAddresses[i])))); return result; }
void IntendedStructureChain::dumpInContext(PrintStream& out, DumpContext* context) const { out.print( "(global = ", RawPointer(m_globalObject), ", head = ", pointerDumpInContext(m_head, context), ", vector = ["); CommaPrinter comma; for (unsigned i = 0; i < m_vector.size(); ++i) out.print(comma, pointerDumpInContext(m_vector[i], context)); out.print("])"); }
AutomaticThread::~AutomaticThread() { if (verbose) dataLog(RawPointer(this), ": Deleting AutomaticThread.\n"); LockHolder locker(*m_lock); // It's possible that we're in a waiting state with the thread shut down. This is a goofy way to // die, but it could happen. m_condition->remove(locker, this); }
JSValue OSRExitSite::toJS(ExecState* exec) const { VM& vm = exec->vm(); JSArray* result = constructEmptyArray(exec, 0); if (UNLIKELY(vm.exception())) return jsUndefined(); for (unsigned i = 0; i < m_codeAddresses.size(); ++i) result->putDirectIndex(exec, i, jsString(exec, toString(RawPointer(m_codeAddresses[i])))); return result; }
void CodeBlockJettisoningWatchpoint::fireInternal() { if (DFG::shouldShowDisassembly()) dataLog("Firing watchpoint ", RawPointer(this), " on ", *m_codeBlock, "\n"); m_codeBlock->jettison(CountReoptimization); if (isOnList()) remove(); }
void JITDisassembler::dump(PrintStream& out, LinkBuffer& linkBuffer) { out.print("Baseline JIT code for ", CodeBlockWithJITType(m_codeBlock, JITCode::BaselineJIT), ", instruction count = ", m_codeBlock->instructionCount(), "\n"); out.print(" Code at [", RawPointer(linkBuffer.debugAddress()), ", ", RawPointer(static_cast<char*>(linkBuffer.debugAddress()) + linkBuffer.debugSize()), "):\n"); dumpDisassembly(out, linkBuffer, m_startOfCode, m_labelForBytecodeIndexInMainPath[0]); MacroAssembler::Label firstSlowLabel; for (unsigned i = 0; i < m_labelForBytecodeIndexInSlowPath.size(); ++i) { if (m_labelForBytecodeIndexInSlowPath[i].isSet()) { firstSlowLabel = m_labelForBytecodeIndexInSlowPath[i]; break; } } dumpForInstructions(out, linkBuffer, " ", m_labelForBytecodeIndexInMainPath, firstSlowLabel.isSet() ? firstSlowLabel : m_endOfSlowPath); out.print(" (End Of Main Path)\n"); dumpForInstructions(out, linkBuffer, " (S) ", m_labelForBytecodeIndexInSlowPath, m_endOfSlowPath); out.print(" (End Of Slow Path)\n"); dumpDisassembly(out, linkBuffer, m_endOfSlowPath, m_endOfCode); }
JSValue VM::throwException(ExecState* exec, JSValue error) { if (Options::breakOnThrow()) { dataLog("In call frame ", RawPointer(exec), " for code block ", *exec->codeBlock(), "\n"); CRASH(); } ASSERT(exec == topCallFrame || exec == exec->lexicalGlobalObject()->globalExec() || exec == exec->vmEntryGlobalObject()->globalExec()); Vector<StackFrame> stackTrace; interpreter->getStackTrace(stackTrace); m_exceptionStack = RefCountedArray<StackFrame>(stackTrace); m_exception = error; if (stackTrace.isEmpty() || !error.isObject()) return error; JSObject* exception = asObject(error); StackFrame stackFrame; for (unsigned i = 0 ; i < stackTrace.size(); ++i) { stackFrame = stackTrace.at(i); if (stackFrame.bytecodeOffset) break; } if (!hasErrorInfo(exec, exception)) { // FIXME: We should only really be adding these properties to VM generated exceptions, // but the inspector currently requires these for all thrown objects. unsigned line; unsigned column; stackFrame.computeLineAndColumn(line, column); exception->putDirect(*this, Identifier(this, "line"), jsNumber(line), ReadOnly | DontDelete); exception->putDirect(*this, Identifier(this, "column"), jsNumber(column), ReadOnly | DontDelete); if (!stackFrame.sourceURL.isEmpty()) exception->putDirect(*this, Identifier(this, "sourceURL"), jsString(this, stackFrame.sourceURL), ReadOnly | DontDelete); } if (exception->isErrorInstance() && static_cast<ErrorInstance*>(exception)->appendSourceToMessage()) { FindFirstCallerFrameWithCodeblockFunctor functor(exec); topCallFrame->iterate(functor); CallFrame* callFrame = functor.foundCallFrame(); unsigned stackIndex = functor.index(); if (callFrame && callFrame->codeBlock()) { stackFrame = stackTrace.at(stackIndex); appendSourceToError(callFrame, static_cast<ErrorInstance*>(exception), stackFrame.bytecodeOffset); } } if (exception->hasProperty(exec, this->propertyNames->stack)) return error; exception->putDirect(*this, propertyNames->stack, interpreter->stackTraceAsString(topCallFrame, stackTrace), DontEnum); return error; }
void JSValue::dumpForBacktrace(PrintStream& out) const { if (!*this) out.print("<JSValue()>"); else if (isInt32()) out.printf("%d", asInt32()); else if (isDouble()) out.printf("%lf", asDouble()); else if (isCell()) { if (asCell()->inherits(JSString::info())) { JSString* string = jsCast<JSString*>(asCell()); const StringImpl* impl = string->tryGetValueImpl(); if (impl) out.print("\"", impl, "\""); else out.print("(unresolved string)"); } else if (asCell()->inherits(Structure::info())) { out.print("Structure[ ", asCell()->structure()->classInfo()->className); #if USE(JSVALUE64) out.print(" ID: ", asCell()->structureID()); #endif out.print("]: ", RawPointer(asCell())); } else { out.print("Cell[", asCell()->structure()->classInfo()->className); #if USE(JSVALUE64) out.print(" ID: ", asCell()->structureID()); #endif out.print("]: ", RawPointer(asCell())); } } else if (isTrue()) out.print("True"); else if (isFalse()) out.print("False"); else if (isNull()) out.print("Null"); else if (isUndefined()) out.print("Undefined"); else out.print("INVALID"); }
void ShadowChicken::Packet::dump(PrintStream& out) const { if (!*this) { out.print("empty"); return; } if (isPrologue()) { out.print( "{callee = ", RawPointer(callee), ", frame = ", RawPointer(frame), ", callerFrame = ", RawPointer(callerFrame), "}"); return; } if (isTail()) { out.print("tail:{frame = ", RawPointer(frame), "}"); return; } ASSERT(isThrow()); out.print("throw"); }