CString MacroAssemblerCodeRef::disassembly() const { StringPrintStream out; if (!tryToDisassemble(out, "")) return CString(); return out.toCString(); }
void Value::deepDump(PrintStream& out) const { out.print(m_type, " ", *this, " = ", m_opcode); out.print("("); CommaPrinter comma; for (Value* child : children()) out.print(comma, pointerDump(child)); if (m_origin) out.print(comma, m_origin); { StringPrintStream stringOut; dumpMeta(stringOut); CString string = stringOut.toCString(); if (string.length()) out.print(comma, string); } { CString string = toCString(effects()); if (string.length()) out.print(comma, string); } out.print(")"); }
Vector<JITDisassembler::DumpedOp> JITDisassembler::dumpVectorForInstructions(LinkBuffer& linkBuffer, const char* prefix, Vector<MacroAssembler::Label>& labels, MacroAssembler::Label endLabel) { StringPrintStream out; Vector<DumpedOp> result; for (unsigned i = 0; i < labels.size();) { if (!labels[i].isSet()) { i++; continue; } out.reset(); result.append(DumpedOp()); result.last().index = i; out.print(prefix); m_codeBlock->dumpBytecode(out, i); for (unsigned nextIndex = i + 1; ; nextIndex++) { if (nextIndex >= labels.size()) { dumpDisassembly(out, linkBuffer, labels[i], endLabel); result.last().disassembly = out.toCString(); return result; } if (labels[nextIndex].isSet()) { dumpDisassembly(out, linkBuffer, labels[i], labels[nextIndex]); result.last().disassembly = out.toCString(); i = nextIndex; break; } } } return result; }
BytecodeSequence::BytecodeSequence(CodeBlock* codeBlock) { StringPrintStream out; for (unsigned i = 0; i < codeBlock->numberOfArgumentValueProfiles(); ++i) { ConcurrentJSLocker locker(codeBlock->m_lock); CString description = codeBlock->valueProfileForArgument(i)->briefDescription(locker); if (!description.length()) continue; out.reset(); out.print("arg", i, ": ", description); m_header.append(out.toCString()); } StubInfoMap stubInfos; codeBlock->getStubInfoMap(stubInfos); for (unsigned bytecodeIndex = 0; bytecodeIndex < codeBlock->instructions().size();) { out.reset(); codeBlock->dumpBytecode(out, bytecodeIndex, stubInfos); m_sequence.append(Bytecode(bytecodeIndex, codeBlock->vm()->interpreter->getOpcodeID(codeBlock->instructions()[bytecodeIndex].u.opcode), out.toCString())); bytecodeIndex += opcodeLength( codeBlock->vm()->interpreter->getOpcodeID( codeBlock->instructions()[bytecodeIndex].u.opcode)); } }
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 ObjectToStringAdaptiveInferredPropertyValueWatchpoint::handleFire(const FireDetail& detail) { StringPrintStream out; out.print("Adaptation of ", key(), " failed: ", detail); StringFireDetail stringDetail(out.toCString().data()); m_structureRareData->clearObjectToStringValue(); }
void ObjectToStringAdaptiveStructureWatchpoint::fireInternal(const FireDetail& detail) { if (m_key.isWatchable(PropertyCondition::EnsureWatchability)) { install(); return; } StringPrintStream out; out.print("ObjectToStringValue Adaptation of ", m_key, " failed: ", detail); StringFireDetail stringDetail(out.toCString().data()); m_structureRareData->clearObjectToStringValue(); }
void Phase::beginPhase() { if (Options::verboseValidationFailure()) { StringPrintStream out; m_graph.dump(out); m_graphDumpBeforePhase = out.toCString(); } if (!shouldDumpGraphAtEachPhase(m_graph.m_plan.mode())) return; dataLog("Beginning DFG phase ", m_name, ".\n"); dataLog("Before ", m_name, ":\n"); m_graph.dump(); }
CString ExceptionScope::unexpectedExceptionMessage() { StringPrintStream out; out.println("Unexpected exception observed on thread ", currentThread(), " at:"); auto currentStack = StackTrace::captureStackTrace(Options::unexpectedExceptionStackTraceLimit(), 1); currentStack->dump(out, " "); if (!m_vm.nativeStackTraceOfLastThrow()) return CString(); out.println("The exception was thrown from thread ", m_vm.throwingThread(), " at:"); m_vm.nativeStackTraceOfLastThrow()->dump(out, " "); return out.toCString(); }
void AdaptiveStructureWatchpoint::fireInternal(const FireDetail& detail) { if (m_key.isWatchable(PropertyCondition::EnsureWatchability)) { install(); return; } if (DFG::shouldDumpDisassembly()) { 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); }
LinkBuffer::CodeRef LinkBuffer::finalizeCodeWithDisassembly(const char* format, ...) { CodeRef result = finalizeCodeWithoutDisassembly(); if (m_alreadyDisassembled) return result; StringPrintStream out; out.printf("Generated JIT code for "); va_list argList; va_start(argList, format); out.vprintf(format, argList); va_end(argList); out.printf(":\n"); out.printf(" Code at [%p, %p):\n", result.code().executableAddress(), static_cast<char*>(result.code().executableAddress()) + result.size()); CString header = out.toCString(); if (Options::asyncDisassembly()) { disassembleAsynchronously(header, result, m_size, " "); return result; } dataLog(header); disassemble(result.code(), m_size, " ", WTF::dataFile()); return result; }
BytecodeSequence::BytecodeSequence(CodeBlock* codeBlock) { StringPrintStream out; #if ENABLE(VALUE_PROFILER) for (unsigned i = 0; i < codeBlock->numberOfArgumentValueProfiles(); ++i) { CString description = codeBlock->valueProfileForArgument(i)->briefDescription(); if (!description.length()) continue; out.reset(); out.print("arg", i, " (r", argumentToOperand(i), "): ", description); m_header.append(out.toCString()); } #endif // ENABLE(VALUE_PROFILER) for (unsigned bytecodeIndex = 0; bytecodeIndex < codeBlock->instructions().size();) { out.reset(); codeBlock->dumpBytecode(out, bytecodeIndex); m_sequence.append(Bytecode(bytecodeIndex, codeBlock->globalData()->interpreter->getOpcodeID(codeBlock->instructions()[bytecodeIndex].u.opcode), out.toCString())); bytecodeIndex += opcodeLength( codeBlock->globalData()->interpreter->getOpcodeID( codeBlock->instructions()[bytecodeIndex].u.opcode)); } }
void JITDisassembler::reportToProfiler(Profiler::Compilation* compilation, LinkBuffer& linkBuffer) { StringPrintStream out; dumpHeader(out, linkBuffer); compilation->addDescription(Profiler::CompiledBytecode(Profiler::OriginStack(), out.toCString())); out.reset(); dumpDisassembly(out, linkBuffer, m_startOfCode, m_labelForBytecodeIndexInMainPath[0]); compilation->addDescription(Profiler::CompiledBytecode(Profiler::OriginStack(), out.toCString())); reportInstructions(compilation, linkBuffer, " ", m_labelForBytecodeIndexInMainPath, firstSlowLabel()); compilation->addDescription(Profiler::CompiledBytecode(Profiler::OriginStack(), " (End Of Main Path)\n")); reportInstructions(compilation, linkBuffer, " (S) ", m_labelForBytecodeIndexInSlowPath, m_endOfSlowPath); compilation->addDescription(Profiler::CompiledBytecode(Profiler::OriginStack(), " (End Of Slow Path)\n")); out.reset(); dumpDisassembly(out, linkBuffer, m_endOfSlowPath, m_endOfCode); compilation->addDescription(Profiler::CompiledBytecode(Profiler::OriginStack(), out.toCString())); }
VM::VM(VMType vmType, HeapType heapType) : m_apiLock(adoptRef(new JSLock(this))) #if ENABLE(ASSEMBLER) , executableAllocator(*this) #endif , heap(this, heapType) , vmType(vmType) , clientData(0) , topCallFrame(CallFrame::noCaller()) , arrayConstructorTable(fastNew<HashTable>(JSC::arrayConstructorTable)) , arrayPrototypeTable(fastNew<HashTable>(JSC::arrayPrototypeTable)) , booleanPrototypeTable(fastNew<HashTable>(JSC::booleanPrototypeTable)) , dateTable(fastNew<HashTable>(JSC::dateTable)) , dateConstructorTable(fastNew<HashTable>(JSC::dateConstructorTable)) , errorPrototypeTable(fastNew<HashTable>(JSC::errorPrototypeTable)) , globalObjectTable(fastNew<HashTable>(JSC::globalObjectTable)) , jsonTable(fastNew<HashTable>(JSC::jsonTable)) , mathTable(fastNew<HashTable>(JSC::mathTable)) , numberConstructorTable(fastNew<HashTable>(JSC::numberConstructorTable)) , numberPrototypeTable(fastNew<HashTable>(JSC::numberPrototypeTable)) , objectConstructorTable(fastNew<HashTable>(JSC::objectConstructorTable)) , privateNamePrototypeTable(fastNew<HashTable>(JSC::privateNamePrototypeTable)) , regExpTable(fastNew<HashTable>(JSC::regExpTable)) , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable)) , regExpPrototypeTable(fastNew<HashTable>(JSC::regExpPrototypeTable)) , stringConstructorTable(fastNew<HashTable>(JSC::stringConstructorTable)) , identifierTable(vmType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable()) , propertyNames(new CommonIdentifiers(this)) , emptyList(new MarkedArgumentBuffer) , parserArena(adoptPtr(new ParserArena)) , keywords(adoptPtr(new Keywords(this))) , interpreter(0) , jsArrayClassInfo(&JSArray::s_info) , jsFinalObjectClassInfo(&JSFinalObject::s_info) #if ENABLE(DFG_JIT) , sizeOfLastScratchBuffer(0) #endif , dynamicGlobalObject(0) , cachedUTCOffset(QNaN) , m_enabledProfiler(0) , m_regExpCache(new RegExpCache(this)) #if ENABLE(REGEXP_TRACING) , m_rtTraceList(new RTTraceList()) #endif #ifndef NDEBUG , exclusiveThread(0) #endif , m_newStringsSinceLastHashCons(0) #if ENABLE(ASSEMBLER) , m_canUseAssembler(enableAssembler(executableAllocator)) #endif #if ENABLE(JIT) , m_canUseJIT(m_canUseAssembler && Options::useJIT()) #endif #if ENABLE(YARR_JIT) , m_canUseRegExpJIT(m_canUseAssembler && Options::useRegExpJIT()) #endif #if ENABLE(GC_VALIDATION) , m_initializingObjectClass(0) #endif , m_inDefineOwnProperty(false) , m_codeCache(CodeCache::create()) { interpreter = new Interpreter(*this); // Need to be careful to keep everything consistent here JSLockHolder lock(this); IdentifierTable* existingEntryIdentifierTable = wtfThreadData().setCurrentIdentifierTable(identifierTable); structureStructure.set(*this, Structure::createStructure(*this)); structureRareDataStructure.set(*this, StructureRareData::createStructure(*this, 0, jsNull())); debuggerActivationStructure.set(*this, DebuggerActivation::createStructure(*this, 0, jsNull())); terminatedExecutionErrorStructure.set(*this, TerminatedExecutionError::createStructure(*this, 0, jsNull())); stringStructure.set(*this, JSString::createStructure(*this, 0, jsNull())); notAnObjectStructure.set(*this, JSNotAnObject::createStructure(*this, 0, jsNull())); propertyNameIteratorStructure.set(*this, JSPropertyNameIterator::createStructure(*this, 0, jsNull())); getterSetterStructure.set(*this, GetterSetter::createStructure(*this, 0, jsNull())); apiWrapperStructure.set(*this, JSAPIValueWrapper::createStructure(*this, 0, jsNull())); JSScopeStructure.set(*this, JSScope::createStructure(*this, 0, jsNull())); executableStructure.set(*this, ExecutableBase::createStructure(*this, 0, jsNull())); nativeExecutableStructure.set(*this, NativeExecutable::createStructure(*this, 0, jsNull())); evalExecutableStructure.set(*this, EvalExecutable::createStructure(*this, 0, jsNull())); programExecutableStructure.set(*this, ProgramExecutable::createStructure(*this, 0, jsNull())); functionExecutableStructure.set(*this, FunctionExecutable::createStructure(*this, 0, jsNull())); regExpStructure.set(*this, RegExp::createStructure(*this, 0, jsNull())); sharedSymbolTableStructure.set(*this, SharedSymbolTable::createStructure(*this, 0, jsNull())); structureChainStructure.set(*this, StructureChain::createStructure(*this, 0, jsNull())); sparseArrayValueMapStructure.set(*this, SparseArrayValueMap::createStructure(*this, 0, jsNull())); withScopeStructure.set(*this, JSWithScope::createStructure(*this, 0, jsNull())); unlinkedFunctionExecutableStructure.set(*this, UnlinkedFunctionExecutable::createStructure(*this, 0, jsNull())); unlinkedProgramCodeBlockStructure.set(*this, UnlinkedProgramCodeBlock::createStructure(*this, 0, jsNull())); unlinkedEvalCodeBlockStructure.set(*this, UnlinkedEvalCodeBlock::createStructure(*this, 0, jsNull())); unlinkedFunctionCodeBlockStructure.set(*this, UnlinkedFunctionCodeBlock::createStructure(*this, 0, jsNull())); propertyTableStructure.set(*this, PropertyTable::createStructure(*this, 0, jsNull())); smallStrings.initializeCommonStrings(*this); wtfThreadData().setCurrentIdentifierTable(existingEntryIdentifierTable); #if ENABLE(JIT) jitStubs = adoptPtr(new JITThunks()); performPlatformSpecificJITAssertions(this); #endif interpreter->initialize(this->canUseJIT()); #if ENABLE(JIT) initializeHostCallReturnValue(); // This is needed to convince the linker not to drop host call return support. #endif heap.notifyIsSafeToCollect(); LLInt::Data::performAssertions(*this); if (Options::enableProfiler()) { m_perBytecodeProfiler = adoptPtr(new Profiler::Database(*this)); StringPrintStream pathOut; #if !OS(WINCE) const char* profilerPath = getenv("JSC_PROFILER_PATH"); if (profilerPath) pathOut.print(profilerPath, "/"); #endif pathOut.print("JSCProfile-", getCurrentProcessID(), "-", m_perBytecodeProfiler->databaseID(), ".json"); m_perBytecodeProfiler->registerToSaveAtExit(pathOut.toCString().data()); } #if ENABLE(DFG_JIT) if (canUseJIT()) m_dfgState = adoptPtr(new DFG::LongLivedState()); #endif }
void Disassembler::append(Vector<Disassembler::DumpedOp>& result, StringPrintStream& out, CodeOrigin& previousOrigin) { result.append(DumpedOp(previousOrigin, out.toCString())); previousOrigin = CodeOrigin(); out.reset(); }
VM::VM(VMType vmType, HeapType heapType) : m_apiLock(adoptRef(new JSLock(this))) #if ENABLE(ASSEMBLER) , executableAllocator(*this) #endif , heap(this, heapType) , vmType(vmType) , clientData(0) , topVMEntryFrame(nullptr) , topCallFrame(CallFrame::noCaller()) , m_atomicStringTable(vmType == Default ? wtfThreadData().atomicStringTable() : new AtomicStringTable) , propertyNames(nullptr) , emptyList(new MarkedArgumentBuffer) , customGetterSetterFunctionMap(*this) , stringCache(*this) , prototypeMap(*this) , interpreter(0) , jsArrayClassInfo(JSArray::info()) , jsFinalObjectClassInfo(JSFinalObject::info()) , sizeOfLastScratchBuffer(0) , entryScope(0) , m_regExpCache(new RegExpCache(this)) #if ENABLE(REGEXP_TRACING) , m_rtTraceList(new RTTraceList()) #endif #if ENABLE(ASSEMBLER) , m_canUseAssembler(enableAssembler(executableAllocator)) #endif #if ENABLE(JIT) , m_canUseJIT(m_canUseAssembler && Options::useJIT()) #endif #if ENABLE(YARR_JIT) , m_canUseRegExpJIT(m_canUseAssembler && Options::useRegExpJIT()) #endif #if ENABLE(GC_VALIDATION) , m_initializingObjectClass(0) #endif , m_stackPointerAtVMEntry(0) , m_stackLimit(0) #if !ENABLE(JIT) , m_jsStackLimit(0) #endif #if ENABLE(FTL_JIT) , m_ftlStackLimit(0) , m_largestFTLStackSize(0) #endif , m_inDefineOwnProperty(false) , m_codeCache(std::make_unique<CodeCache>()) , m_enabledProfiler(nullptr) , m_builtinExecutables(std::make_unique<BuiltinExecutables>(*this)) , m_typeProfilerEnabledCount(0) , m_controlFlowProfilerEnabledCount(0) { interpreter = new Interpreter(*this); StackBounds stack = wtfThreadData().stack(); updateReservedZoneSize(Options::reservedZoneSize()); #if !ENABLE(JIT) interpreter->stack().setReservedZoneSize(Options::reservedZoneSize()); #endif setLastStackTop(stack.origin()); // Need to be careful to keep everything consistent here JSLockHolder lock(this); AtomicStringTable* existingEntryAtomicStringTable = wtfThreadData().setCurrentAtomicStringTable(m_atomicStringTable); propertyNames = new CommonIdentifiers(this); structureStructure.set(*this, Structure::createStructure(*this)); structureRareDataStructure.set(*this, StructureRareData::createStructure(*this, 0, jsNull())); terminatedExecutionErrorStructure.set(*this, TerminatedExecutionError::createStructure(*this, 0, jsNull())); stringStructure.set(*this, JSString::createStructure(*this, 0, jsNull())); notAnObjectStructure.set(*this, JSNotAnObject::createStructure(*this, 0, jsNull())); propertyNameEnumeratorStructure.set(*this, JSPropertyNameEnumerator::createStructure(*this, 0, jsNull())); getterSetterStructure.set(*this, GetterSetter::createStructure(*this, 0, jsNull())); customGetterSetterStructure.set(*this, CustomGetterSetter::createStructure(*this, 0, jsNull())); scopedArgumentsTableStructure.set(*this, ScopedArgumentsTable::createStructure(*this, 0, jsNull())); apiWrapperStructure.set(*this, JSAPIValueWrapper::createStructure(*this, 0, jsNull())); JSScopeStructure.set(*this, JSScope::createStructure(*this, 0, jsNull())); executableStructure.set(*this, ExecutableBase::createStructure(*this, 0, jsNull())); nativeExecutableStructure.set(*this, NativeExecutable::createStructure(*this, 0, jsNull())); evalExecutableStructure.set(*this, EvalExecutable::createStructure(*this, 0, jsNull())); programExecutableStructure.set(*this, ProgramExecutable::createStructure(*this, 0, jsNull())); functionExecutableStructure.set(*this, FunctionExecutable::createStructure(*this, 0, jsNull())); #if ENABLE(WEBASSEMBLY) webAssemblyExecutableStructure.set(*this, WebAssemblyExecutable::createStructure(*this, 0, jsNull())); #endif moduleProgramExecutableStructure.set(*this, ModuleProgramExecutable::createStructure(*this, 0, jsNull())); regExpStructure.set(*this, RegExp::createStructure(*this, 0, jsNull())); symbolStructure.set(*this, Symbol::createStructure(*this, 0, jsNull())); symbolTableStructure.set(*this, SymbolTable::createStructure(*this, 0, jsNull())); structureChainStructure.set(*this, StructureChain::createStructure(*this, 0, jsNull())); sparseArrayValueMapStructure.set(*this, SparseArrayValueMap::createStructure(*this, 0, jsNull())); templateRegistryKeyStructure.set(*this, JSTemplateRegistryKey::createStructure(*this, 0, jsNull())); arrayBufferNeuteringWatchpointStructure.set(*this, ArrayBufferNeuteringWatchpoint::createStructure(*this)); unlinkedFunctionExecutableStructure.set(*this, UnlinkedFunctionExecutable::createStructure(*this, 0, jsNull())); unlinkedProgramCodeBlockStructure.set(*this, UnlinkedProgramCodeBlock::createStructure(*this, 0, jsNull())); unlinkedEvalCodeBlockStructure.set(*this, UnlinkedEvalCodeBlock::createStructure(*this, 0, jsNull())); unlinkedFunctionCodeBlockStructure.set(*this, UnlinkedFunctionCodeBlock::createStructure(*this, 0, jsNull())); unlinkedModuleProgramCodeBlockStructure.set(*this, UnlinkedModuleProgramCodeBlock::createStructure(*this, 0, jsNull())); propertyTableStructure.set(*this, PropertyTable::createStructure(*this, 0, jsNull())); weakMapDataStructure.set(*this, WeakMapData::createStructure(*this, 0, jsNull())); inferredValueStructure.set(*this, InferredValue::createStructure(*this, 0, jsNull())); inferredTypeStructure.set(*this, InferredType::createStructure(*this, 0, jsNull())); inferredTypeTableStructure.set(*this, InferredTypeTable::createStructure(*this, 0, jsNull())); functionRareDataStructure.set(*this, FunctionRareData::createStructure(*this, 0, jsNull())); generatorFrameStructure.set(*this, GeneratorFrame::createStructure(*this, 0, jsNull())); exceptionStructure.set(*this, Exception::createStructure(*this, 0, jsNull())); promiseDeferredStructure.set(*this, JSPromiseDeferred::createStructure(*this, 0, jsNull())); internalPromiseDeferredStructure.set(*this, JSInternalPromiseDeferred::createStructure(*this, 0, jsNull())); programCodeBlockStructure.set(*this, ProgramCodeBlock::createStructure(*this, 0, jsNull())); moduleProgramCodeBlockStructure.set(*this, ModuleProgramCodeBlock::createStructure(*this, 0, jsNull())); evalCodeBlockStructure.set(*this, EvalCodeBlock::createStructure(*this, 0, jsNull())); functionCodeBlockStructure.set(*this, FunctionCodeBlock::createStructure(*this, 0, jsNull())); #if ENABLE(WEBASSEMBLY) webAssemblyCodeBlockStructure.set(*this, WebAssemblyCodeBlock::createStructure(*this, 0, jsNull())); #endif iterationTerminator.set(*this, JSFinalObject::create(*this, JSFinalObject::createStructure(*this, 0, jsNull(), 1))); nativeStdFunctionCellStructure.set(*this, NativeStdFunctionCell::createStructure(*this, 0, jsNull())); smallStrings.initializeCommonStrings(*this); wtfThreadData().setCurrentAtomicStringTable(existingEntryAtomicStringTable); #if ENABLE(JIT) jitStubs = std::make_unique<JITThunks>(); allCalleeSaveRegisterOffsets = std::make_unique<RegisterAtOffsetList>(RegisterSet::vmCalleeSaveRegisters(), RegisterAtOffsetList::ZeroBased); #endif arityCheckData = std::make_unique<CommonSlowPaths::ArityCheckData>(); #if ENABLE(FTL_JIT) ftlThunks = std::make_unique<FTL::Thunks>(); #endif // ENABLE(FTL_JIT) interpreter->initialize(); #if ENABLE(JIT) initializeHostCallReturnValue(); // This is needed to convince the linker not to drop host call return support. #endif heap.notifyIsSafeToCollect(); LLInt::Data::performAssertions(*this); if (Options::useProfiler()) { m_perBytecodeProfiler = std::make_unique<Profiler::Database>(*this); StringPrintStream pathOut; const char* profilerPath = getenv("JSC_PROFILER_PATH"); if (profilerPath) pathOut.print(profilerPath, "/"); pathOut.print("JSCProfile-", getCurrentProcessID(), "-", m_perBytecodeProfiler->databaseID(), ".json"); m_perBytecodeProfiler->registerToSaveAtExit(pathOut.toCString().data()); } callFrameForCatch = nullptr; #if ENABLE(DFG_JIT) if (canUseJIT()) dfgState = std::make_unique<DFG::LongLivedState>(); #endif // Initialize this last, as a free way of asserting that VM initialization itself // won't use this. m_typedArrayController = adoptRef(new SimpleTypedArrayController()); m_bytecodeIntrinsicRegistry = std::make_unique<BytecodeIntrinsicRegistry>(*this); if (Options::useTypeProfiler()) enableTypeProfiler(); if (Options::useControlFlowProfiler()) enableControlFlowProfiler(); #if ENABLE(SAMPLING_PROFILER) if (Options::useSamplingProfiler()) { setShouldBuildPCToCodeOriginMapping(); m_samplingProfiler = adoptRef(new SamplingProfiler(*this, Stopwatch::create())); m_samplingProfiler->start(); } #endif // ENABLE(SAMPLING_PROFILER) if (Options::alwaysGeneratePCToCodeOriginMap()) setShouldBuildPCToCodeOriginMapping(); if (Options::watchdog()) { std::chrono::milliseconds timeoutMillis(Options::watchdog()); Watchdog& watchdog = ensureWatchdog(); watchdog.setTimeLimit(timeoutMillis); } }
void dumpNodeFlags(PrintStream& actualOut, NodeFlags flags) { StringPrintStream out; CommaPrinter comma("|"); if (flags & NodeResultMask) { switch (flags & NodeResultMask) { case NodeResultJS: out.print(comma, "JS"); break; case NodeResultNumber: out.print(comma, "Number"); break; case NodeResultInt32: out.print(comma, "Int32"); break; case NodeResultInt52: out.print(comma, "Int52"); break; case NodeResultBoolean: out.print(comma, "Boolean"); break; case NodeResultStorage: out.print(comma, "Storage"); break; default: RELEASE_ASSERT_NOT_REACHED(); break; } } if (flags & NodeMustGenerate) out.print(comma, "MustGen"); if (flags & NodeHasVarArgs) out.print(comma, "VarArgs"); if (flags & NodeClobbersWorld) out.print(comma, "Clobbers"); if (flags & NodeMightClobber) out.print(comma, "MightClobber"); if (flags & NodeResultMask) { if (!(flags & NodeBytecodeUsesAsNumber) && !(flags & NodeBytecodeNeedsNegZero)) out.print(comma, "PureInt"); else if (!(flags & NodeBytecodeUsesAsNumber)) out.print(comma, "PureInt(w/ neg zero)"); else if (!(flags & NodeBytecodeNeedsNegZero)) out.print(comma, "PureNum"); if (flags & NodeBytecodeUsesAsOther) out.print(comma, "UseAsOther"); } if (flags & NodeMayOverflow) out.print(comma, "MayOverflow"); if (flags & NodeMayNegZero) out.print(comma, "MayNegZero"); if (flags & NodeBytecodeUsesAsInt) out.print(comma, "UseAsInt"); if (!(flags & NodeDoesNotExit)) out.print(comma, "CanExit"); CString string = out.toCString(); if (!string.length()) actualOut.print("<empty>"); else actualOut.print(string); }
void link(State& state) { Graph& graph = state.graph; CodeBlock* codeBlock = graph.m_codeBlock; VM& vm = graph.m_vm; // LLVM will create its own jump tables as needed. codeBlock->clearSwitchJumpTables(); #if !FTL_USES_B3 // What LLVM's stackmaps call stackSizeForLocals and what we call frameRegisterCount have a simple // relationship, though it's not obvious from reading the code. The easiest way to understand them // is to look at stackOffset, i.e. what you have to add to FP to get SP. For LLVM that is just: // // stackOffset == -state.jitCode->stackmaps.stackSizeForLocals() // // The way we define frameRegisterCount is that it satisfies this equality: // // stackOffset == virtualRegisterForLocal(frameRegisterCount - 1).offset() * sizeof(Register) // // We can simplify this when we apply virtualRegisterForLocal(): // // stackOffset == (-1 - (frameRegisterCount - 1)) * sizeof(Register) // stackOffset == (-1 - frameRegisterCount + 1) * sizeof(Register) // stackOffset == -frameRegisterCount * sizeof(Register) // // Therefore we just have: // // frameRegisterCount == -stackOffset / sizeof(Register) // // If we substitute what we have above, we get: // // frameRegisterCount == -(-state.jitCode->stackmaps.stackSizeForLocals()) / sizeof(Register) // frameRegisterCount == state.jitCode->stackmaps.stackSizeForLocals() / sizeof(Register) state.jitCode->common.frameRegisterCount = state.jitCode->stackmaps.stackSizeForLocals() / sizeof(void*); #endif state.jitCode->common.requiredRegisterCountForExit = graph.requiredRegisterCountForExit(); if (!graph.m_plan.inlineCallFrames->isEmpty()) state.jitCode->common.inlineCallFrames = graph.m_plan.inlineCallFrames; graph.registerFrozenValues(); // Create the entrypoint. Note that we use this entrypoint totally differently // depending on whether we're doing OSR entry or not. CCallHelpers jit(&vm, codeBlock); std::unique_ptr<LinkBuffer> linkBuffer; CCallHelpers::Address frame = CCallHelpers::Address( CCallHelpers::stackPointerRegister, -static_cast<int32_t>(AssemblyHelpers::prologueStackPointerDelta())); if (Profiler::Compilation* compilation = graph.compilation()) { compilation->addDescription( Profiler::OriginStack(), toCString("Generated FTL JIT code for ", CodeBlockWithJITType(codeBlock, JITCode::FTLJIT), ", instruction count = ", graph.m_codeBlock->instructionCount(), ":\n")); graph.ensureDominators(); graph.ensureNaturalLoops(); const char* prefix = " "; DumpContext dumpContext; StringPrintStream out; Node* lastNode = 0; for (size_t blockIndex = 0; blockIndex < graph.numBlocks(); ++blockIndex) { BasicBlock* block = graph.block(blockIndex); if (!block) continue; graph.dumpBlockHeader(out, prefix, block, Graph::DumpLivePhisOnly, &dumpContext); compilation->addDescription(Profiler::OriginStack(), out.toCString()); out.reset(); for (size_t nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) { Node* node = block->at(nodeIndex); Profiler::OriginStack stack; if (node->origin.semantic.isSet()) { stack = Profiler::OriginStack( *vm.m_perBytecodeProfiler, codeBlock, node->origin.semantic); } if (graph.dumpCodeOrigin(out, prefix, lastNode, node, &dumpContext)) { compilation->addDescription(stack, out.toCString()); out.reset(); } graph.dump(out, prefix, node, &dumpContext); compilation->addDescription(stack, out.toCString()); out.reset(); if (node->origin.semantic.isSet()) lastNode = node; } } dumpContext.dump(out, prefix); compilation->addDescription(Profiler::OriginStack(), out.toCString()); out.reset(); out.print(" Disassembly:\n"); #if FTL_USES_B3 out.print(" <not implemented yet>\n"); #else for (unsigned i = 0; i < state.jitCode->handles().size(); ++i) { if (state.codeSectionNames[i] != SECTION_NAME("text")) continue; ExecutableMemoryHandle* handle = state.jitCode->handles()[i].get(); disassemble( MacroAssemblerCodePtr(handle->start()), handle->sizeInBytes(), " ", out, LLVMSubset); } #endif compilation->addDescription(Profiler::OriginStack(), out.toCString()); out.reset(); state.jitCode->common.compilation = compilation; } switch (graph.m_plan.mode) { case FTLMode: { CCallHelpers::JumpList mainPathJumps; jit.load32( frame.withOffset(sizeof(Register) * JSStack::ArgumentCount), GPRInfo::regT1); mainPathJumps.append(jit.branch32( CCallHelpers::AboveOrEqual, GPRInfo::regT1, CCallHelpers::TrustedImm32(codeBlock->numParameters()))); jit.emitFunctionPrologue(); jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); jit.store32( CCallHelpers::TrustedImm32(CallSiteIndex(0).bits()), CCallHelpers::tagFor(JSStack::ArgumentCount)); jit.storePtr(GPRInfo::callFrameRegister, &vm.topCallFrame); CCallHelpers::Call callArityCheck = jit.call(); #if !ASSERT_DISABLED // FIXME: need to make this call register with exception handling somehow. This is // part of a bigger problem: FTL should be able to handle exceptions. // https://bugs.webkit.org/show_bug.cgi?id=113622 // Until then, use a JIT ASSERT. jit.load64(vm.addressOfException(), GPRInfo::regT1); jit.jitAssertIsNull(GPRInfo::regT1); #endif jit.move(GPRInfo::returnValueGPR, GPRInfo::argumentGPR0); jit.emitFunctionEpilogue(); mainPathJumps.append(jit.branchTest32(CCallHelpers::Zero, GPRInfo::argumentGPR0)); jit.emitFunctionPrologue(); CCallHelpers::Call callArityFixup = jit.call(); jit.emitFunctionEpilogue(); mainPathJumps.append(jit.jump()); linkBuffer = std::make_unique<LinkBuffer>(vm, jit, codeBlock, JITCompilationCanFail); if (linkBuffer->didFailToAllocate()) { state.allocationFailed = true; return; } linkBuffer->link(callArityCheck, codeBlock->m_isConstructor ? operationConstructArityCheck : operationCallArityCheck); linkBuffer->link(callArityFixup, FunctionPtr((vm.getCTIStub(arityFixupGenerator)).code().executableAddress())); linkBuffer->link(mainPathJumps, CodeLocationLabel(bitwise_cast<void*>(state.generatedFunction))); state.jitCode->initializeAddressForCall(MacroAssemblerCodePtr(bitwise_cast<void*>(state.generatedFunction))); break; } case FTLForOSREntryMode: { // We jump to here straight from DFG code, after having boxed up all of the // values into the scratch buffer. Everything should be good to go - at this // point we've even done the stack check. Basically we just have to make the // call to the LLVM-generated code. CCallHelpers::Label start = jit.label(); jit.emitFunctionEpilogue(); CCallHelpers::Jump mainPathJump = jit.jump(); linkBuffer = std::make_unique<LinkBuffer>(vm, jit, codeBlock, JITCompilationCanFail); if (linkBuffer->didFailToAllocate()) { state.allocationFailed = true; return; } linkBuffer->link(mainPathJump, CodeLocationLabel(bitwise_cast<void*>(state.generatedFunction))); state.jitCode->initializeAddressForCall(linkBuffer->locationOf(start)); break; } default: RELEASE_ASSERT_NOT_REACHED(); break; } state.finalizer->entrypointLinkBuffer = WTFMove(linkBuffer); state.finalizer->function = state.generatedFunction; state.finalizer->jitCode = state.jitCode; }
void dumpNodeFlags(PrintStream& actualOut, NodeFlags flags) { StringPrintStream out; CommaPrinter comma("|"); if (flags & NodeResultMask) { switch (flags & NodeResultMask) { case NodeResultJS: out.print(comma, "JS"); break; case NodeResultNumber: out.print(comma, "Number"); break; case NodeResultDouble: out.print(comma, "Double"); break; case NodeResultInt32: out.print(comma, "Int32"); break; case NodeResultInt52: out.print(comma, "Int52"); break; case NodeResultBoolean: out.print(comma, "Boolean"); break; case NodeResultStorage: out.print(comma, "Storage"); break; default: RELEASE_ASSERT_NOT_REACHED(); break; } } if (flags & NodeMustGenerate) out.print(comma, "MustGen"); if (flags & NodeHasVarArgs) out.print(comma, "VarArgs"); if (flags & NodeResultMask) { if (!(flags & NodeBytecodeUsesAsNumber) && !(flags & NodeBytecodeNeedsNegZero)) out.print(comma, "PureInt"); else if (!(flags & NodeBytecodeUsesAsNumber)) out.print(comma, "PureInt(w/ neg zero)"); else if (!(flags & NodeBytecodeNeedsNegZero)) out.print(comma, "PureNum"); if (flags & NodeBytecodeUsesAsOther) out.print(comma, "UseAsOther"); } if (flags & NodeMayHaveNonIntResult) out.print(comma, "MayHaveNonIntResult"); if (flags & NodeMayOverflowInt52) out.print(comma, "MayOverflowInt52"); if (flags & NodeMayOverflowInt32InBaseline) out.print(comma, "MayOverflowInt32InBaseline"); if (flags & NodeMayOverflowInt32InDFG) out.print(comma, "MayOverflowInt32InDFG"); if (flags & NodeMayNegZeroInBaseline) out.print(comma, "MayNegZeroInBaseline"); if (flags & NodeMayNegZeroInDFG) out.print(comma, "MayNegZeroInDFG"); if (flags & NodeBytecodeUsesAsInt) out.print(comma, "UseAsInt"); if (flags & NodeBytecodeUsesAsArrayIndex) out.print(comma, "ReallyWantsInt"); if (flags & NodeIsFlushed) out.print(comma, "IsFlushed"); CString string = out.toCString(); if (!string.length()) actualOut.print("<empty>"); else actualOut.print(string); }
void link(State& state) { Graph& graph = state.graph; CodeBlock* codeBlock = graph.m_codeBlock; VM& vm = graph.m_vm; // LLVM will create its own jump tables as needed. codeBlock->clearSwitchJumpTables(); // FIXME: Need to know the real frame register count. // https://bugs.webkit.org/show_bug.cgi?id=125727 state.jitCode->common.frameRegisterCount = 1000; state.jitCode->common.requiredRegisterCountForExit = graph.requiredRegisterCountForExit(); if (!graph.m_plan.inlineCallFrames->isEmpty()) state.jitCode->common.inlineCallFrames = graph.m_plan.inlineCallFrames; graph.registerFrozenValues(); // Create the entrypoint. Note that we use this entrypoint totally differently // depending on whether we're doing OSR entry or not. CCallHelpers jit(&vm, codeBlock); std::unique_ptr<LinkBuffer> linkBuffer; CCallHelpers::Address frame = CCallHelpers::Address( CCallHelpers::stackPointerRegister, -static_cast<int32_t>(AssemblyHelpers::prologueStackPointerDelta())); if (Profiler::Compilation* compilation = graph.compilation()) { compilation->addDescription( Profiler::OriginStack(), toCString("Generated FTL JIT code for ", CodeBlockWithJITType(codeBlock, JITCode::FTLJIT), ", instruction count = ", graph.m_codeBlock->instructionCount(), ":\n")); graph.m_dominators.computeIfNecessary(graph); graph.m_naturalLoops.computeIfNecessary(graph); const char* prefix = " "; DumpContext dumpContext; StringPrintStream out; Node* lastNode = 0; for (size_t blockIndex = 0; blockIndex < graph.numBlocks(); ++blockIndex) { BasicBlock* block = graph.block(blockIndex); if (!block) continue; graph.dumpBlockHeader(out, prefix, block, Graph::DumpLivePhisOnly, &dumpContext); compilation->addDescription(Profiler::OriginStack(), out.toCString()); out.reset(); for (size_t nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) { Node* node = block->at(nodeIndex); if (!node->willHaveCodeGenOrOSR() && !Options::showAllDFGNodes()) continue; Profiler::OriginStack stack; if (node->origin.semantic.isSet()) { stack = Profiler::OriginStack( *vm.m_perBytecodeProfiler, codeBlock, node->origin.semantic); } if (graph.dumpCodeOrigin(out, prefix, lastNode, node, &dumpContext)) { compilation->addDescription(stack, out.toCString()); out.reset(); } graph.dump(out, prefix, node, &dumpContext); compilation->addDescription(stack, out.toCString()); out.reset(); if (node->origin.semantic.isSet()) lastNode = node; } } dumpContext.dump(out, prefix); compilation->addDescription(Profiler::OriginStack(), out.toCString()); out.reset(); out.print(" Disassembly:\n"); for (unsigned i = 0; i < state.jitCode->handles().size(); ++i) { if (state.codeSectionNames[i] != SECTION_NAME("text")) continue; ExecutableMemoryHandle* handle = state.jitCode->handles()[i].get(); disassemble( MacroAssemblerCodePtr(handle->start()), handle->sizeInBytes(), " ", out, LLVMSubset); } compilation->addDescription(Profiler::OriginStack(), out.toCString()); out.reset(); state.jitCode->common.compilation = compilation; } switch (graph.m_plan.mode) { case FTLMode: { CCallHelpers::JumpList mainPathJumps; jit.load32( frame.withOffset(sizeof(Register) * JSStack::ArgumentCount), GPRInfo::regT1); mainPathJumps.append(jit.branch32( CCallHelpers::AboveOrEqual, GPRInfo::regT1, CCallHelpers::TrustedImm32(codeBlock->numParameters()))); jit.emitFunctionPrologue(); jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); jit.store32( CCallHelpers::TrustedImm32(CallFrame::Location::encodeAsBytecodeOffset(0)), CCallHelpers::tagFor(JSStack::ArgumentCount)); jit.storePtr(GPRInfo::callFrameRegister, &vm.topCallFrame); CCallHelpers::Call callArityCheck = jit.call(); #if !ASSERT_DISABLED // FIXME: need to make this call register with exception handling somehow. This is // part of a bigger problem: FTL should be able to handle exceptions. // https://bugs.webkit.org/show_bug.cgi?id=113622 // Until then, use a JIT ASSERT. jit.load64(vm.addressOfException(), GPRInfo::regT1); jit.jitAssertIsNull(GPRInfo::regT1); #endif jit.move(GPRInfo::returnValueGPR, GPRInfo::regT0); jit.emitFunctionEpilogue(); mainPathJumps.append(jit.branchTest32(CCallHelpers::Zero, GPRInfo::regT0)); jit.emitFunctionPrologue(); jit.move(CCallHelpers::TrustedImmPtr(vm.arityCheckFailReturnThunks->returnPCsFor(vm, codeBlock->numParameters())), GPRInfo::regT7); jit.loadPtr(CCallHelpers::BaseIndex(GPRInfo::regT7, GPRInfo::regT0, CCallHelpers::timesPtr()), GPRInfo::regT7); CCallHelpers::Call callArityFixup = jit.call(); jit.emitFunctionEpilogue(); mainPathJumps.append(jit.jump()); linkBuffer = std::make_unique<LinkBuffer>(vm, jit, codeBlock, JITCompilationMustSucceed); linkBuffer->link(callArityCheck, codeBlock->m_isConstructor ? operationConstructArityCheck : operationCallArityCheck); linkBuffer->link(callArityFixup, FunctionPtr((vm.getCTIStub(arityFixupGenerator)).code().executableAddress())); linkBuffer->link(mainPathJumps, CodeLocationLabel(bitwise_cast<void*>(state.generatedFunction))); state.jitCode->initializeAddressForCall(MacroAssemblerCodePtr(bitwise_cast<void*>(state.generatedFunction))); break; } case FTLForOSREntryMode: { // We jump to here straight from DFG code, after having boxed up all of the // values into the scratch buffer. Everything should be good to go - at this // point we've even done the stack check. Basically we just have to make the // call to the LLVM-generated code. CCallHelpers::Label start = jit.label(); jit.emitFunctionEpilogue(); CCallHelpers::Jump mainPathJump = jit.jump(); linkBuffer = std::make_unique<LinkBuffer>(vm, jit, codeBlock, JITCompilationMustSucceed); linkBuffer->link(mainPathJump, CodeLocationLabel(bitwise_cast<void*>(state.generatedFunction))); state.jitCode->initializeAddressForCall(linkBuffer->locationOf(start)); break; } default: RELEASE_ASSERT_NOT_REACHED(); break; } state.finalizer->entrypointLinkBuffer = WTF::move(linkBuffer); state.finalizer->function = state.generatedFunction; state.finalizer->jitCode = state.jitCode; }
CString Special::name() const { StringPrintStream out; dumpImpl(out); return out.toCString(); }
CString ArrayProfile::briefDescriptionWithoutUpdating(const ConcurrentJITLocker&) { StringPrintStream out; bool hasPrinted = false; if (m_observedArrayModes) { if (hasPrinted) out.print(", "); out.print(ArrayModesDump(m_observedArrayModes)); 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(); }
Vector<Disassembler::DumpedOp> Disassembler::createDumpList(LinkBuffer& linkBuffer) { StringPrintStream out; Vector<DumpedOp> result; CodeOrigin previousOrigin = CodeOrigin(); dumpHeader(out, linkBuffer); append(result, out, previousOrigin); m_graph.m_dominators.computeIfNecessary(m_graph); m_graph.m_naturalLoops.computeIfNecessary(m_graph); const char* prefix = " "; const char* disassemblyPrefix = " "; Node* lastNode = 0; MacroAssembler::Label previousLabel = m_startOfCode; for (size_t blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) { BasicBlock* block = m_graph.block(blockIndex); if (!block) continue; dumpDisassembly(out, disassemblyPrefix, linkBuffer, previousLabel, m_labelForBlockIndex[blockIndex], lastNode); append(result, out, previousOrigin); m_graph.dumpBlockHeader(out, prefix, block, Graph::DumpLivePhisOnly, &m_dumpContext); append(result, out, previousOrigin); Node* lastNodeForDisassembly = block->at(0); for (size_t i = 0; i < block->size(); ++i) { MacroAssembler::Label currentLabel; HashMap<Node*, MacroAssembler::Label>::iterator iter = m_labelForNode.find(block->at(i)); if (iter != m_labelForNode.end()) currentLabel = iter->value; 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.numBlocks()) currentLabel = m_labelForBlockIndex[blockIndex + 1]; else currentLabel = m_endOfMainPath; } dumpDisassembly(out, disassemblyPrefix, linkBuffer, previousLabel, currentLabel, lastNodeForDisassembly); append(result, out, previousOrigin); previousOrigin = block->at(i)->origin.semantic; if (m_graph.dumpCodeOrigin(out, prefix, lastNode, block->at(i), &m_dumpContext)) { append(result, out, previousOrigin); previousOrigin = block->at(i)->origin.semantic; } m_graph.dump(out, prefix, block->at(i), &m_dumpContext); lastNode = block->at(i); lastNodeForDisassembly = block->at(i); } } dumpDisassembly(out, disassemblyPrefix, linkBuffer, previousLabel, m_endOfMainPath, lastNode); append(result, out, previousOrigin); out.print(prefix, "(End Of Main Path)\n"); append(result, out, previousOrigin); dumpDisassembly(out, disassemblyPrefix, linkBuffer, previousLabel, m_endOfCode, 0); append(result, out, previousOrigin); m_dumpContext.dump(out, prefix); append(result, out, previousOrigin); return result; }
void logRegisterPressure(Code& code) { const unsigned totalColumns = 200; const unsigned registerColumns = 100; RegLiveness liveness(code); for (BasicBlock* block : code) { RegLiveness::LocalCalc localCalc(liveness, block); block->dumpHeader(WTF::dataFile()); Vector<CString> instDumps; for (unsigned instIndex = block->size(); instIndex--;) { Inst& inst = block->at(instIndex); Inst* prevInst = block->get(instIndex - 1); localCalc.execute(instIndex); RegisterSet set; set.setAll(localCalc.live()); Inst::forEachDefWithExtraClobberedRegs<Reg>( prevInst, &inst, [&] (Reg reg, Arg::Role, Arg::Type, Arg::Width) { set.set(reg); }); StringPrintStream instOut; StringPrintStream lineOut; lineOut.print(" "); if (set.numberOfSetRegisters()) { set.forEach( [&] (Reg reg) { CString text = toCString(" ", reg); if (text.length() + lineOut.length() > totalColumns) { instOut.print(lineOut.toCString(), "\n"); lineOut.reset(); lineOut.print(" "); } lineOut.print(text); }); lineOut.print(":"); } if (lineOut.length() > registerColumns) { instOut.print(lineOut.toCString(), "\n"); lineOut.reset(); } while (lineOut.length() < registerColumns) lineOut.print(" "); lineOut.print(" "); lineOut.print(inst); instOut.print(lineOut.toCString(), "\n"); instDumps.append(instOut.toCString()); } for (unsigned i = instDumps.size(); i--;) dataLog(instDumps[i]); block->dumpFooter(WTF::dataFile()); } }
void dumpSpeculation(PrintStream& out, SpeculatedType value) { if (value == SpecNone) { out.print("None"); return; } StringPrintStream myOut; bool isTop = true; if ((value & SpecCell) == SpecCell) myOut.print("Cell"); else { if ((value & SpecObject) == SpecObject) myOut.print("Object"); else { if (value & SpecCellOther) myOut.print("Othercell"); else isTop = false; if (value & SpecObjectOther) myOut.print("Otherobj"); else isTop = false; if (value & SpecFinalObject) myOut.print("Final"); else isTop = false; if (value & SpecArray) myOut.print("Array"); else isTop = false; if (value & SpecInt8Array) myOut.print("Int8array"); else isTop = false; if (value & SpecInt16Array) myOut.print("Int16array"); else isTop = false; if (value & SpecInt32Array) myOut.print("Int32array"); else isTop = false; if (value & SpecUint8Array) myOut.print("Uint8array"); else isTop = false; if (value & SpecUint8ClampedArray) myOut.print("Uint8clampedarray"); else isTop = false; if (value & SpecUint16Array) myOut.print("Uint16array"); else isTop = false; if (value & SpecUint32Array) myOut.print("Uint32array"); else isTop = false; if (value & SpecFloat32Array) myOut.print("Float32array"); else isTop = false; if (value & SpecFloat64Array) myOut.print("Float64array"); else isTop = false; if (value & SpecFunction) myOut.print("Function"); else isTop = false; if (value & SpecArguments) myOut.print("Arguments"); else isTop = false; if (value & SpecStringObject) myOut.print("Stringobject"); else isTop = false; } if ((value & SpecString) == SpecString) myOut.print("String"); else { if (value & SpecStringIdent) myOut.print("Stringident"); else isTop = false; if (value & SpecStringVar) myOut.print("Stringvar"); else isTop = false; } } if (value & SpecInt32) myOut.print("Int32"); else isTop = false; if (value & SpecInt52) myOut.print("Int52"); if ((value & SpecDouble) == SpecDouble) myOut.print("Double"); else { if (value & SpecInt52AsDouble) myOut.print("Int52asdouble"); else isTop = false; if (value & SpecNonIntAsDouble) myOut.print("Nonintasdouble"); else isTop = false; if (value & SpecDoubleNaN) myOut.print("Doublenan"); else isTop = false; } if (value & SpecBoolean) myOut.print("Bool"); else isTop = false; if (value & SpecOther) myOut.print("Other"); else isTop = false; if (isTop) out.print("Top"); else out.print(myOut.toCString()); if (value & SpecEmpty) out.print("Empty"); }
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(); }