Changeset 155013 in webkit
- Timestamp:
- Sep 3, 2013, 5:26:57 PM (12 years ago)
- Location:
- trunk/Source
- Files:
-
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/API/JSContextRef.cpp
r153218 r155013 213 213 return toGlobalRef(exec->lexicalGlobalObject()->globalExec()); 214 214 } 215 215 216 class BacktraceFunctor { 217 public: 218 BacktraceFunctor(StringBuilder& builder, unsigned remainingCapacityForFrameCapture) 219 : m_builder(builder) 220 , m_remainingCapacityForFrameCapture(remainingCapacityForFrameCapture) 221 { 222 } 223 224 StackIterator::Status operator()(StackIterator& iter) 225 { 226 if (m_remainingCapacityForFrameCapture) { 227 // If callee is unknown, but we've not added any frame yet, we should 228 // still add the frame, because something called us, and gave us arguments. 229 JSObject* callee = iter->callee(); 230 if (!callee && iter->index()) 231 return StackIterator::Done; 232 233 StringBuilder& builder = m_builder; 234 if (!builder.isEmpty()) 235 builder.append('\n'); 236 builder.append('#'); 237 builder.appendNumber(iter->index()); 238 builder.append(' '); 239 builder.append(iter->functionName()); 240 builder.appendLiteral("() at "); 241 builder.append(iter->sourceURL()); 242 if (iter->isJSFrame()) { 243 builder.append(':'); 244 unsigned lineNumber; 245 unsigned unusedColumn; 246 iter->computeLineAndColumn(lineNumber, unusedColumn); 247 builder.appendNumber(lineNumber); 248 } 249 250 if (!callee) 251 return StackIterator::Done; 252 253 m_remainingCapacityForFrameCapture--; 254 return StackIterator::Continue; 255 } 256 return StackIterator::Done; 257 } 258 259 private: 260 StringBuilder& m_builder; 261 unsigned m_remainingCapacityForFrameCapture; 262 }; 263 216 264 JSStringRef JSContextCreateBacktrace(JSContextRef ctx, unsigned maxStackSize) 217 265 { … … 224 272 StringBuilder builder; 225 273 CallFrame* frame = exec->vm().topCallFrame; 226 size_t i = 0; 274 227 275 ASSERT(maxStackSize); 228 for (StackIterator iter = frame->begin(); iter != frame->end() && maxStackSize--; ++iter, ++i) { 229 JSObject* callee = iter->callee(); 230 // If callee is unknown, but we've not added any frame yet, we should 231 // still add the frame, because something called us, and gave us arguments. 232 if (!callee && i) 233 break; 234 235 if (!builder.isEmpty()) 236 builder.append('\n'); 237 builder.append('#'); 238 builder.appendNumber(i); 239 builder.append(' '); 240 builder.append(iter->functionName()); 241 builder.appendLiteral("() at "); 242 builder.append(iter->sourceURL()); 243 if (iter->isJSFrame()) { 244 builder.append(':'); 245 unsigned lineNumber; 246 unsigned unusedColumn; 247 iter->computeLineAndColumn(lineNumber, unusedColumn); 248 builder.appendNumber(lineNumber); 249 } 250 251 if (!callee) 252 break; 253 } 276 BacktraceFunctor functor(builder, maxStackSize); 277 StackIterator iter = frame->begin(); 278 iter.iterate(functor); 254 279 255 280 return OpaqueJSString::create(builder.toString()).leakRef(); -
trunk/Source/JavaScriptCore/ChangeLog
r155008 r155013 1 2013-09-03 Mark Lam <mark.lam@apple.com> 2 3 Converting StackIterator to a callback interface. 4 https://bugs.webkit.org/show_bug.cgi?id=120564. 5 6 Reviewed by Filip Pizlo. 7 8 * API/JSContextRef.cpp: 9 (BacktraceFunctor::BacktraceFunctor): 10 (BacktraceFunctor::operator()): 11 (JSContextCreateBacktrace): 12 * interpreter/CallFrame.cpp: 13 * interpreter/CallFrame.h: 14 * interpreter/Interpreter.cpp: 15 (JSC::DumpRegisterFunctor::DumpRegisterFunctor): 16 (JSC::DumpRegisterFunctor::operator()): 17 (JSC::Interpreter::dumpRegisters): 18 (JSC::unwindCallFrame): 19 (JSC::GetStackTraceFunctor::GetStackTraceFunctor): 20 (JSC::GetStackTraceFunctor::operator()): 21 (JSC::Interpreter::getStackTrace): 22 (JSC::Interpreter::stackTraceAsString): 23 (JSC::UnwindFunctor::UnwindFunctor): 24 (JSC::UnwindFunctor::operator()): 25 (JSC::Interpreter::unwind): 26 * interpreter/Interpreter.h: 27 * interpreter/StackIterator.cpp: 28 (JSC::StackIterator::numberOfFrames): 29 (JSC::StackIterator::gotoFrameAtIndex): 30 (JSC::StackIterator::gotoNextFrameWithFilter): 31 (JSC::StackIterator::resetIterator): 32 (JSC::StackIterator::Frame::print): 33 (debugPrintCallFrame): 34 (DebugPrintStackFunctor::operator()): 35 (debugPrintStack): Added for debugging convenience. 36 * interpreter/StackIterator.h: 37 (JSC::StackIterator::Frame::index): 38 (JSC::StackIterator::iterate): 39 * jsc.cpp: 40 (FunctionJSCStackFunctor::FunctionJSCStackFunctor): 41 (FunctionJSCStackFunctor::operator()): 42 (functionJSCStack): 43 * profiler/ProfileGenerator.cpp: 44 (JSC::AddParentForConsoleStartFunctor::AddParentForConsoleStartFunctor): 45 (JSC::AddParentForConsoleStartFunctor::foundParent): 46 (JSC::AddParentForConsoleStartFunctor::operator()): 47 (JSC::ProfileGenerator::addParentForConsoleStart): 48 * runtime/JSFunction.cpp: 49 (JSC::RetrieveArgumentsFunctor::RetrieveArgumentsFunctor): 50 (JSC::RetrieveArgumentsFunctor::result): 51 (JSC::RetrieveArgumentsFunctor::operator()): 52 (JSC::retrieveArguments): 53 (JSC::RetrieveCallerFunctionFunctor::RetrieveCallerFunctionFunctor): 54 (JSC::RetrieveCallerFunctionFunctor::result): 55 (JSC::RetrieveCallerFunctionFunctor::operator()): 56 (JSC::retrieveCallerFunction): 57 * runtime/JSGlobalObjectFunctions.cpp: 58 (JSC::GlobalFuncProtoGetterFunctor::GlobalFuncProtoGetterFunctor): 59 (JSC::GlobalFuncProtoGetterFunctor::result): 60 (JSC::GlobalFuncProtoGetterFunctor::operator()): 61 (JSC::globalFuncProtoGetter): 62 (JSC::GlobalFuncProtoSetterFunctor::GlobalFuncProtoSetterFunctor): 63 (JSC::GlobalFuncProtoSetterFunctor::allowsAccess): 64 (JSC::GlobalFuncProtoSetterFunctor::operator()): 65 (JSC::globalFuncProtoSetter): 66 * runtime/ObjectConstructor.cpp: 67 (JSC::ObjectConstructorGetPrototypeOfFunctor::ObjectConstructorGetPrototypeOfFunctor): 68 (JSC::ObjectConstructorGetPrototypeOfFunctor::result): 69 (JSC::ObjectConstructorGetPrototypeOfFunctor::operator()): 70 (JSC::objectConstructorGetPrototypeOf): 71 1 72 2013-09-03 Oliver Hunt <oliver@apple.com> 2 73 -
trunk/Source/JavaScriptCore/interpreter/CallFrame.cpp
r154821 r155013 104 104 } 105 105 106 StackIterator CallFrame::find(JSFunction* calleeFunctionObj, StackIterator::FrameFilter filter)107 {108 ASSERT(this);109 StackIterator iter = StackIterator(this, filter);110 iter.find(calleeFunctionObj);111 return iter;112 }113 114 106 } // namespace JSC -
trunk/Source/JavaScriptCore/interpreter/CallFrame.h
r154902 r155013 285 285 286 286 JS_EXPORT_PRIVATE StackIterator begin(StackIterator::FrameFilter = 0); 287 JS_EXPORT_PRIVATE StackIterator find(JSFunction* calleeFunctionObj, StackIterator::FrameFilter = 0);288 StackIterator end() { return StackIterator::end(); }289 287 290 288 private: -
trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp
r154935 r155013 275 275 } 276 276 277 class DumpRegisterFunctor { 278 public: 279 DumpRegisterFunctor(const Register*& it) 280 : m_hasSkippedFirstFrame(false) 281 , m_it(it) 282 { 283 } 284 285 StackIterator::Status operator()(StackIterator& iter) 286 { 287 if (!m_hasSkippedFirstFrame) { 288 m_hasSkippedFirstFrame = true; 289 return StackIterator::Continue; 290 } 291 292 unsigned line = 0; 293 unsigned unusedColumn = 0; 294 iter->computeLineAndColumn(line, unusedColumn); 295 dataLogF("[ReturnVPC] | %10p | %d (line %d)\n", m_it, iter->bytecodeOffset(), line); 296 ++m_it; 297 return StackIterator::Done; 298 } 299 300 private: 301 bool m_hasSkippedFirstFrame; 302 const Register*& m_it; 303 }; 304 277 305 void Interpreter::dumpRegisters(CallFrame* callFrame) 278 306 { … … 310 338 dataLogF("[ReturnJITPC] | %10p | %p \n", it, pc.jitReturnAddress().value()); 311 339 #endif 340 341 DumpRegisterFunctor functor(it); 312 342 StackIterator iter = callFrame->begin(); 313 ++iter; 314 if (iter != callFrame->end()) { 315 unsigned line = 0; 316 unsigned unusedColumn = 0; 317 iter->computeLineAndColumn(line, unusedColumn); 318 dataLogF("[ReturnVPC] | %10p | %d (line %d)\n", it, iter->bytecodeOffset(), line); 319 ++it; 320 } 343 iter.iterate(functor); 344 321 345 dataLogF("[CodeBlock] | %10p | %p \n", it, callFrame->codeBlock()); 322 346 ++it; … … 367 391 } 368 392 369 NEVER_INLINE bool Interpreter::unwindCallFrame(StackIterator& iter, JSValue exceptionValue)393 static bool unwindCallFrame(StackIterator& iter, JSValue exceptionValue) 370 394 { 371 395 CallFrame* callFrame = iter->callFrame(); … … 475 499 } 476 500 501 class GetStackTraceFunctor { 502 public: 503 GetStackTraceFunctor(VM& vm, Vector<StackFrame>& results, size_t remainingCapacity) 504 : m_vm(vm) 505 , m_results(results) 506 , m_remainingCapacityForFrameCapture(remainingCapacity) 507 { 508 } 509 510 StackIterator::Status operator()(StackIterator& iter) 511 { 512 VM& vm = m_vm; 513 if (m_remainingCapacityForFrameCapture) { 514 if (iter->isJSFrame()) { 515 CodeBlock* codeBlock = iter->codeBlock(); 516 StackFrame s = { 517 Strong<JSObject>(vm, iter->callee()), 518 getStackFrameCodeType(iter), 519 Strong<ExecutableBase>(vm, codeBlock->ownerExecutable()), 520 Strong<UnlinkedCodeBlock>(vm, codeBlock->unlinkedCodeBlock()), 521 codeBlock->source(), 522 codeBlock->ownerExecutable()->lineNo(), 523 codeBlock->firstLineColumnOffset(), 524 codeBlock->sourceOffset(), 525 iter->bytecodeOffset(), 526 iter->sourceURL() 527 }; 528 m_results.append(s); 529 } else { 530 StackFrame s = { Strong<JSObject>(vm, iter->callee()), StackFrameNativeCode, Strong<ExecutableBase>(), Strong<UnlinkedCodeBlock>(), 0, 0, 0, 0, 0, String()}; 531 m_results.append(s); 532 } 533 534 m_remainingCapacityForFrameCapture--; 535 return StackIterator::Continue; 536 } 537 return StackIterator::Done; 538 } 539 540 private: 541 VM& m_vm; 542 Vector<StackFrame>& m_results; 543 size_t m_remainingCapacityForFrameCapture; 544 }; 545 477 546 void Interpreter::getStackTrace(Vector<StackFrame>& results, size_t maxStackSize) 478 547 { … … 482 551 if (!callFrame) 483 552 return; 553 554 GetStackTraceFunctor functor(vm, results, maxStackSize); 484 555 StackIterator iter = callFrame->begin(); 485 for (; iter != callFrame->end() && maxStackSize--; ++iter) { 486 if (iter->isJSFrame()) { 487 CodeBlock* codeBlock = iter->codeBlock(); 488 StackFrame s = { 489 Strong<JSObject>(vm, iter->callee()), 490 getStackFrameCodeType(iter), 491 Strong<ExecutableBase>(vm, codeBlock->ownerExecutable()), 492 Strong<UnlinkedCodeBlock>(vm, codeBlock->unlinkedCodeBlock()), 493 codeBlock->source(), 494 codeBlock->ownerExecutable()->lineNo(), 495 codeBlock->firstLineColumnOffset(), 496 codeBlock->sourceOffset(), 497 iter->bytecodeOffset(), 498 iter->sourceURL() 499 }; 500 results.append(s); 501 } else { 502 StackFrame s = { Strong<JSObject>(vm, iter->callee()), StackFrameNativeCode, Strong<ExecutableBase>(), Strong<UnlinkedCodeBlock>(), 0, 0, 0, 0, 0, String()}; 503 results.append(s); 504 } 505 } 506 } 507 JSString* Interpreter:: stackTraceAsString(ExecState* exec, Vector<StackFrame> stackTrace) 556 iter.iterate(functor); 557 } 558 559 JSString* Interpreter::stackTraceAsString(ExecState* exec, Vector<StackFrame> stackTrace) 508 560 { 509 561 // FIXME: JSStringJoiner could be more efficient than StringBuilder here. … … 516 568 return jsString(&exec->vm(), builder.toString()); 517 569 } 570 571 class UnwindFunctor { 572 public: 573 UnwindFunctor(CallFrame*& callFrame, JSValue& exceptionValue, bool isTermination, CodeBlock*& codeBlock, HandlerInfo*& handler) 574 : m_callFrame(callFrame) 575 , m_exceptionValue(exceptionValue) 576 , m_isTermination(isTermination) 577 , m_codeBlock(codeBlock) 578 , m_handler(handler) 579 { 580 } 581 582 StackIterator::Status operator()(StackIterator& iter) 583 { 584 VM& vm = m_callFrame->vm(); 585 m_callFrame = iter->callFrame(); 586 m_codeBlock = iter->codeBlock(); 587 unsigned bytecodeOffset = iter->bytecodeOffset(); 588 589 if (m_isTermination || !(m_handler = m_codeBlock->handlerForBytecodeOffset(bytecodeOffset))) { 590 if (!unwindCallFrame(iter, m_exceptionValue)) { 591 if (LegacyProfiler* profiler = vm.enabledProfiler()) 592 profiler->exceptionUnwind(m_callFrame); 593 return StackIterator::Done; 594 } 595 } else 596 return StackIterator::Done; 597 598 return StackIterator::Continue; 599 } 600 601 private: 602 CallFrame*& m_callFrame; 603 JSValue& m_exceptionValue; 604 bool m_isTermination; 605 CodeBlock*& m_codeBlock; 606 HandlerInfo*& m_handler; 607 }; 518 608 519 609 NEVER_INLINE HandlerInfo* Interpreter::unwind(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset) … … 550 640 VM& vm = callFrame->vm(); 551 641 ASSERT(callFrame == vm.topCallFrame); 552 for (StackIterator iter = callFrame->begin(); iter != callFrame->end(); ++iter) { 553 callFrame = iter->callFrame(); 554 codeBlock = iter->codeBlock(); 555 bytecodeOffset = iter->bytecodeOffset(); 556 557 if (isTermination || !(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) { 558 if (!unwindCallFrame(iter, exceptionValue)) { 559 if (LegacyProfiler* profiler = vm.enabledProfiler()) 560 profiler->exceptionUnwind(callFrame); 561 return 0; 562 } 563 } else 564 break; 565 } 566 567 if (LegacyProfiler* profiler = callFrame->vm().enabledProfiler()) 642 UnwindFunctor functor(callFrame, exceptionValue, isTermination, codeBlock, handler); 643 StackIterator iter = callFrame->begin(); 644 iter.iterate(functor); 645 if (!handler) 646 return 0; 647 648 if (LegacyProfiler* profiler = vm.enabledProfiler()) 568 649 profiler->exceptionUnwind(callFrame); 569 650 -
trunk/Source/JavaScriptCore/interpreter/Interpreter.h
r154797 r155013 263 263 264 264 void getStackTrace(Vector<StackFrame>& results, size_t maxStackSize = std::numeric_limits<size_t>::max()); 265 NEVER_INLINE bool unwindCallFrame(StackIterator&, JSValue);266 265 267 266 void dumpRegisters(CallFrame*); -
trunk/Source/JavaScriptCore/interpreter/StackIterator.cpp
r154821 r155013 45 45 size_t StackIterator::numberOfFrames() 46 46 { 47 int savedFrameIndex = m_frame Index;47 int savedFrameIndex = m_frame.index(); 48 48 resetIterator(); 49 49 while (m_frame.callFrame()) 50 50 gotoNextFrameWithFilter(); 51 size_t numberOfFrames = m_frame Index;51 size_t numberOfFrames = m_frame.index(); 52 52 53 53 resetIterator(); … … 59 59 void StackIterator::gotoFrameAtIndex(size_t index) 60 60 { 61 while (m_frame.callFrame() && (m_frame Index!= index))61 while (m_frame.callFrame() && (m_frame.index() != index)) 62 62 gotoNextFrameWithFilter(); 63 63 } … … 84 84 break; 85 85 } 86 m_frame Index++;86 m_frame.m_index++; 87 87 } 88 88 89 89 void StackIterator::resetIterator() 90 90 { 91 m_frame Index = 0;91 m_frame.m_index = 0; 92 92 readFrame(m_startFrame); 93 }94 95 StackIterator StackIterator::end()96 {97 return StackIterator(0, 0);98 }99 100 void StackIterator::find(JSFunction* functionObj)101 {102 ASSERT(functionObj);103 JSObject* targetCallee = jsDynamicCast<JSObject*>(functionObj);104 while (m_frame.callFrame()) {105 if (m_frame.callee() == targetCallee)106 break;107 gotoNextFrameWithFilter();108 }109 93 } 110 94 … … 405 389 int i = indentLevel; 406 390 391 if (!this->callFrame()) { 392 printif(i, "frame 0x0\n"); 393 return; 394 } 395 407 396 CodeBlock* codeBlock = this->codeBlock(); 408 printif(i, "frame %p {\n", this );397 printif(i, "frame %p {\n", this->callFrame()); 409 398 410 399 CallFrame* callFrame = m_callFrame; … … 461 450 462 451 #ifndef NDEBUG 452 using JSC::StackIterator; 453 463 454 // For debugging use 464 455 void debugPrintCallFrame(JSC::CallFrame*); … … 469 460 if (!callFrame) 470 461 return; 471 JSC::StackIterator iter = callFrame->begin();462 StackIterator iter = callFrame->begin(); 472 463 iter->print(2); 473 464 } 474 465 466 class DebugPrintStackFunctor { 467 public: 468 StackIterator::Status operator()(StackIterator& iter) 469 { 470 iter->print(2); 471 return StackIterator::Continue; 472 } 473 }; 474 475 475 void debugPrintStack(JSC::CallFrame* topCallFrame) 476 476 { 477 477 if (!topCallFrame) 478 478 return; 479 JSC::StackIterator iter = topCallFrame->begin();480 for (; iter != topCallFrame->end(); ++iter)481 iter->print(2);479 DebugPrintStackFunctor functor; 480 StackIterator iter = topCallFrame->begin(); 481 iter.iterate(functor); 482 482 } 483 483 #endif // !NDEBUG -
trunk/Source/JavaScriptCore/interpreter/StackIterator.h
r154827 r155013 54 54 }; 55 55 56 size_t index() const { return m_index; } 56 57 size_t argumentCountIncludingThis() const { return m_argumentCountIncludingThis; } 57 58 CallFrame* callerFrame() const { return m_callerFrame; } … … 90 91 void setToEnd(); 91 92 93 size_t m_index; 92 94 size_t m_argumentCountIncludingThis; 93 95 CallFrame* m_callerFrame; … … 107 109 typedef bool (*FrameFilter)(Frame*); 108 110 111 enum Status { 112 Continue = 0, 113 Done = 1 114 }; 115 116 // StackIterator::iterate() expects a Functor that implements the following method: 117 // Status operator()(StackIterator&); 118 119 template <typename Functor> void iterate(Functor& functor) 120 { 121 while (m_frame.callFrame()) { 122 Status status = functor(*this); 123 if (status != Continue) 124 break; 125 gotoNextFrameWithFilter(); 126 } 127 } 128 109 129 JS_EXPORT_PRIVATE size_t numberOfFrames(); 110 130 … … 112 132 ALWAYS_INLINE Frame* operator->() { return &m_frame; } 113 133 114 inline bool operator==(const StackIterator&);115 bool operator!=(const StackIterator& other) { return !(*this == other); }116 void operator++() { gotoNextFrameWithFilter(); }117 void find(JSFunction*);118 119 134 private: 120 135 JS_EXPORT_PRIVATE StackIterator(CallFrame* startFrame, FrameFilter = 0); 121 136 122 JS_EXPORT_PRIVATE static StackIterator end();123 137 void gotoFrameAtIndex(size_t frameIndex); 124 138 void gotoNextFrame(); … … 133 147 134 148 CallFrame* m_startFrame; 135 size_t m_frameIndex;136 149 FrameFilter m_filter; 137 150 Frame m_frame; … … 140 153 }; 141 154 142 inline bool StackIterator::operator==(const StackIterator& other)143 {144 return (m_frame.callFrame() == other.m_frame.callFrame())145 #if ENABLE(DFG_JIT)146 && (m_frame.inlineCallFrame() == other.m_frame.inlineCallFrame())147 #endif148 ;149 }150 151 155 } // namespace JSC 152 156 -
trunk/Source/JavaScriptCore/jsc.cpp
r154797 r155013 327 327 } 328 328 329 class FunctionJSCStackFunctor { 330 public: 331 FunctionJSCStackFunctor(StringBuilder& trace) 332 : m_trace(trace) 333 { 334 } 335 336 StackIterator::Status operator()(StackIterator& iter) 337 { 338 m_trace.append(String::format(" %zu %s\n", iter->index(), iter->toString().utf8().data())); 339 return StackIterator::Continue; 340 } 341 342 private: 343 StringBuilder& m_trace; 344 }; 345 329 346 EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState* exec) 330 347 { … … 332 349 trace.appendLiteral("--> Stack trace:\n"); 333 350 334 int i = 0;335 for (StackIterator iter = exec->begin(); iter != exec->end(); ++iter, ++i)336 trace.append(String::format(" %i %s\n", i, iter->toString().utf8().data()));351 FunctionJSCStackFunctor functor(trace); 352 StackIterator iter = exec->begin(); 353 iter.iterate(functor); 337 354 fprintf(stderr, "%s", trace.toString().utf8().data()); 338 355 return JSValue::encode(jsUndefined()); -
trunk/Source/JavaScriptCore/profiler/ProfileGenerator.cpp
r153218 r155013 58 58 } 59 59 60 class AddParentForConsoleStartFunctor { 61 public: 62 AddParentForConsoleStartFunctor(ExecState* exec, RefPtr<ProfileNode>& head, RefPtr<ProfileNode>& currentNode) 63 : m_exec(exec) 64 , m_hasSkippedFirstFrame(false) 65 , m_foundParent(false) 66 , m_head(head) 67 , m_currentNode(currentNode) 68 { 69 } 70 71 bool foundParent() const { return m_foundParent; } 72 73 StackIterator::Status operator()(StackIterator& iter) 74 { 75 if (!m_hasSkippedFirstFrame) { 76 m_hasSkippedFirstFrame = true; 77 return StackIterator::Continue; 78 } 79 80 unsigned line = 0; 81 unsigned unusedColumn = 0; 82 iter->computeLineAndColumn(line, unusedColumn); 83 m_currentNode = ProfileNode::create(m_exec, LegacyProfiler::createCallIdentifier(m_exec, iter->callee(), iter->sourceURL(), line), m_head.get(), m_head.get()); 84 m_head->insertNode(m_currentNode.get()); 85 86 m_foundParent = true; 87 return StackIterator::Done; 88 } 89 90 private: 91 ExecState* m_exec; 92 bool m_hasSkippedFirstFrame; 93 bool m_foundParent; 94 RefPtr<ProfileNode>& m_head; 95 RefPtr<ProfileNode>& m_currentNode; 96 }; 97 60 98 void ProfileGenerator::addParentForConsoleStart(ExecState* exec) 61 99 { 100 AddParentForConsoleStartFunctor functor(exec, m_head, m_currentNode); 62 101 StackIterator iter = exec->begin(); 63 ++iter; 64 if (iter == exec->end()) { 102 iter.iterate(functor); 103 104 if (!functor.foundParent()) { 65 105 m_currentNode = ProfileNode::create(exec, LegacyProfiler::createCallIdentifier(exec, JSValue(), String(), 0), m_head.get(), m_head.get()); 66 106 m_head->insertNode(m_currentNode.get()); 67 return; 68 } 69 unsigned line = 0; 70 unsigned unusedColumn = 0; 71 iter->computeLineAndColumn(line, unusedColumn); 72 m_currentNode = ProfileNode::create(exec, LegacyProfiler::createCallIdentifier(exec, iter->callee(), iter->sourceURL(), line), m_head.get(), m_head.get()); 73 m_head->insertNode(m_currentNode.get()); 107 } 74 108 } 75 109 -
trunk/Source/JavaScriptCore/runtime/JSFunction.cpp
r154797 r155013 183 183 } 184 184 185 class RetrieveArgumentsFunctor { 186 public: 187 RetrieveArgumentsFunctor(JSFunction* functionObj) 188 : m_targetCallee(jsDynamicCast<JSObject*>(functionObj)) 189 , m_result(jsNull()) 190 { 191 } 192 193 JSValue result() const { return m_result; } 194 195 StackIterator::Status operator()(StackIterator& iter) 196 { 197 JSObject* callee = iter->callee(); 198 if (callee != m_targetCallee) 199 return StackIterator::Continue; 200 201 m_result = JSValue(iter->arguments()); 202 return StackIterator::Done; 203 } 204 205 private: 206 JSObject* m_targetCallee; 207 JSValue m_result; 208 }; 209 185 210 static JSValue retrieveArguments(ExecState* exec, JSFunction* functionObj) 186 211 { 187 StackIterator iter = exec->find(functionObj); 188 return iter != exec->end() ? JSValue(iter->arguments()) : jsNull(); 212 RetrieveArgumentsFunctor functor(functionObj); 213 StackIterator iter = exec->begin(); 214 iter.iterate(functor); 215 return functor.result(); 189 216 } 190 217 … … 204 231 } 205 232 233 class RetrieveCallerFunctionFunctor { 234 public: 235 RetrieveCallerFunctionFunctor(JSFunction* functionObj) 236 : m_targetCallee(jsDynamicCast<JSObject*>(functionObj)) 237 , m_hasFoundFrame(false) 238 , m_hasSkippedToCallerFrame(false) 239 , m_result(jsNull()) 240 { 241 } 242 243 JSValue result() const { return m_result; } 244 245 StackIterator::Status operator()(StackIterator& iter) 246 { 247 JSObject* callee = iter->callee(); 248 if (!m_hasFoundFrame && (callee != m_targetCallee)) 249 return StackIterator::Continue; 250 251 m_hasFoundFrame = true; 252 if (!m_hasSkippedToCallerFrame) { 253 m_hasSkippedToCallerFrame = true; 254 return StackIterator::Continue; 255 } 256 257 if (callee) 258 m_result = callee; 259 return StackIterator::Done; 260 } 261 262 private: 263 JSObject* m_targetCallee; 264 bool m_hasFoundFrame; 265 bool m_hasSkippedToCallerFrame; 266 JSValue m_result; 267 }; 268 206 269 static JSValue retrieveCallerFunction(ExecState* exec, JSFunction* functionObj) 207 270 { 208 StackIterator iter = exec->find(functionObj, skipOverBoundFunctions);209 if (iter != exec->end())210 ++iter;211 return iter != exec->end() && iter->callee() ? iter->callee() : jsNull();271 RetrieveCallerFunctionFunctor functor(functionObj); 272 StackIterator iter = exec->begin(skipOverBoundFunctions); 273 iter.iterate(functor); 274 return functor.result(); 212 275 } 213 276 -
trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
r154902 r155013 707 707 } 708 708 709 class GlobalFuncProtoGetterFunctor { 710 public: 711 GlobalFuncProtoGetterFunctor(JSObject* thisObject) 712 : m_hasSkippedFirstFrame(false) 713 , m_thisObject(thisObject) 714 , m_result(JSValue::encode(jsUndefined())) 715 { 716 } 717 718 EncodedJSValue result() { return m_result; } 719 720 StackIterator::Status operator()(StackIterator& iter) 721 { 722 if (!m_hasSkippedFirstFrame) { 723 m_hasSkippedFirstFrame = true; 724 return StackIterator::Continue; 725 } 726 727 if (m_thisObject->allowsAccessFrom(iter->callFrame())) 728 m_result = JSValue::encode(m_thisObject->prototype()); 729 730 return StackIterator::Done; 731 } 732 733 private: 734 bool m_hasSkippedFirstFrame; 735 JSObject* m_thisObject; 736 EncodedJSValue m_result; 737 }; 738 709 739 EncodedJSValue JSC_HOST_CALL globalFuncProtoGetter(ExecState* exec) 710 740 { … … 714 744 return JSValue::encode(exec->thisValue().synthesizePrototype(exec)); 715 745 746 GlobalFuncProtoGetterFunctor functor(thisObject); 716 747 StackIterator iter = exec->begin(); 717 ++iter; 718 if ((iter == exec->end()) || !thisObject->allowsAccessFrom(iter->callFrame())) 719 return JSValue::encode(jsUndefined()); 720 721 return JSValue::encode(thisObject->prototype()); 722 } 748 iter.iterate(functor); 749 return functor.result(); 750 } 751 752 class GlobalFuncProtoSetterFunctor { 753 public: 754 GlobalFuncProtoSetterFunctor(JSObject* thisObject) 755 : m_hasSkippedFirstFrame(false) 756 , m_allowsAccess(false) 757 , m_thisObject(thisObject) 758 { 759 } 760 761 bool allowsAccess() const { return m_allowsAccess; } 762 763 StackIterator::Status operator()(StackIterator& iter) 764 { 765 if (!m_hasSkippedFirstFrame) { 766 m_hasSkippedFirstFrame = true; 767 return StackIterator::Continue; 768 } 769 770 m_allowsAccess = m_thisObject->allowsAccessFrom(iter->callFrame()); 771 return StackIterator::Done; 772 } 773 774 private: 775 bool m_hasSkippedFirstFrame; 776 bool m_allowsAccess; 777 JSObject* m_thisObject; 778 }; 723 779 724 780 EncodedJSValue JSC_HOST_CALL globalFuncProtoSetter(ExecState* exec) … … 732 788 return JSValue::encode(jsUndefined()); 733 789 790 GlobalFuncProtoSetterFunctor functor(thisObject); 734 791 StackIterator iter = exec->begin(); 735 ++iter;736 if ( (iter == exec->end()) || !thisObject->allowsAccessFrom(iter->callFrame()))792 iter.iterate(functor); 793 if (!functor.allowsAccess()) 737 794 return JSValue::encode(jsUndefined()); 738 795 -
trunk/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
r154797 r155013 132 132 } 133 133 134 class ObjectConstructorGetPrototypeOfFunctor { 135 public: 136 ObjectConstructorGetPrototypeOfFunctor(JSObject* object) 137 : m_hasSkippedFirstFrame(false) 138 , m_object(object) 139 , m_result(JSValue::encode(jsUndefined())) 140 { 141 } 142 143 EncodedJSValue result() const { return m_result; } 144 145 StackIterator::Status operator()(StackIterator& iter) 146 { 147 if (!m_hasSkippedFirstFrame) { 148 m_hasSkippedFirstFrame = true; 149 return StackIterator::Continue; 150 } 151 152 if (m_object->allowsAccessFrom(iter->callFrame())) 153 m_result = JSValue::encode(m_object->prototype()); 154 return StackIterator::Done; 155 } 156 157 private: 158 bool m_hasSkippedFirstFrame; 159 JSObject* m_object; 160 EncodedJSValue m_result; 161 }; 162 134 163 EncodedJSValue JSC_HOST_CALL objectConstructorGetPrototypeOf(ExecState* exec) 135 164 { … … 137 166 return throwVMError(exec, createTypeError(exec, ASCIILiteral("Requested prototype of a value that is not an object."))); 138 167 JSObject* object = asObject(exec->argument(0)); 168 ObjectConstructorGetPrototypeOfFunctor functor(object); 139 169 StackIterator iter = exec->begin(); 140 ++iter; 141 if ((iter == exec->end()) || !object->allowsAccessFrom(iter->callFrame())) 142 return JSValue::encode(jsUndefined()); 143 return JSValue::encode(object->prototype()); 170 iter.iterate(functor); 171 return functor.result(); 144 172 } 145 173 -
trunk/Source/WebCore/ChangeLog
r155008 r155013 1 2013-09-03 Mark Lam <mark.lam@apple.com> 2 3 Converting StackIterator to a callback interface. 4 https://bugs.webkit.org/show_bug.cgi?id=120564. 5 6 Reviewed by Filip Pizlo. 7 8 No new tests. 9 10 * bindings/js/JSXMLHttpRequestCustom.cpp: 11 (WebCore::SendFunctor::SendFunctor): 12 (WebCore::SendFunctor::hasViableFrame): 13 (WebCore::SendFunctor::operator()): 14 (WebCore::JSXMLHttpRequest::send): 15 * bindings/js/ScriptCallStackFactory.cpp: 16 (WebCore::CreateScriptCallStackFunctor::CreateScriptCallStackFunctor): 17 (WebCore::CreateScriptCallStackFunctor::operator()): 18 (WebCore::createScriptCallStack): 19 (WebCore::CreateScriptCallStackForConsoleFunctor::CreateScriptCallStackForConsoleFunctor): 20 (WebCore::CreateScriptCallStackForConsoleFunctor::operator()): 21 1 22 2013-09-03 Oliver Hunt <oliver@apple.com> 2 23 … … 3297 3318 (WebCore::findDropZone): 3298 3319 3299 <<<<<<< .mine3300 3320 2013-08-28 Benjamin Poulain <benjamin@webkit.org> 3301 3321 … … 3343 3363 (WebCore::findDropZone): 3344 3364 3345 =======3346 3365 2013-08-28 Rob Buis <rwlbuis@webkit.org> 3347 3366 … … 3426 3445 (WebCore::AXSearchFieldCancelButtonText): 3427 3446 3428 >>>>>>> .r1547793429 3447 2013-08-28 Eric Carlson <eric.carlson@apple.com> 3430 3448 -
trunk/Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp
r154992 r155013 113 113 } 114 114 115 class SendFunctor { 116 public: 117 SendFunctor() 118 : m_hasSkippedFirstFrame(false) 119 , m_hasViableFrame(false) 120 { 121 } 122 123 bool hasViableFrame() const { return m_hasViableFrame; } 124 125 StackIterator::Status operator()(StackIterator&) 126 { 127 if (!m_hasSkippedFirstFrame) { 128 m_hasSkippedFirstFrame = true; 129 return StackIterator::Continue; 130 } 131 132 m_hasViableFrame = true; 133 return StackIterator::Done; 134 } 135 136 private: 137 bool m_hasSkippedFirstFrame; 138 bool m_hasViableFrame; 139 }; 140 115 141 JSValue JSXMLHttpRequest::send(ExecState* exec) 116 142 { … … 139 165 } 140 166 167 SendFunctor functor; 141 168 StackIterator iter = exec->begin(); 142 ++iter;143 if ( iter != exec->end()) {169 iter.iterate(functor); 170 if (functor.hasViableFrame()) { 144 171 unsigned line = 0; 145 172 unsigned unusuedColumn = 0; -
trunk/Source/WebCore/bindings/js/ScriptCallStackFactory.cpp
r154797 r155013 55 55 class ScriptExecutionContext; 56 56 57 class CreateScriptCallStackFunctor { 58 public: 59 CreateScriptCallStackFunctor(Vector<ScriptCallFrame>& frames, size_t remainingCapacity) 60 : m_frames(frames) 61 , m_remainingCapacityForFrameCapture(remainingCapacity) 62 { 63 } 64 65 StackIterator::Status operator()(StackIterator& iter) 66 { 67 if (m_remainingCapacityForFrameCapture) { 68 unsigned line; 69 unsigned column; 70 iter->computeLineAndColumn(line, column); 71 m_frames.append(ScriptCallFrame(iter->functionName(), iter->sourceURL(), line, column)); 72 73 m_remainingCapacityForFrameCapture--; 74 return StackIterator::Continue; 75 } 76 return StackIterator::Done; 77 } 78 79 private: 80 Vector<ScriptCallFrame>& m_frames; 81 size_t m_remainingCapacityForFrameCapture; 82 }; 83 57 84 PassRefPtr<ScriptCallStack> createScriptCallStack(size_t maxStackSize, bool emptyIsAllowed) 58 85 { … … 60 87 if (JSC::ExecState* exec = JSMainThreadExecState::currentState()) { 61 88 CallFrame* frame = exec->vm().topCallFrame; 62 for (StackIterator iter = frame->begin(); iter != frame->end() && maxStackSize--; ++iter) { 63 unsigned line; 64 unsigned column; 65 iter->computeLineAndColumn(line, column); 66 frames.append(ScriptCallFrame(iter->functionName(), iter->sourceURL(), line, column)); 67 } 89 CreateScriptCallStackFunctor functor(frames, maxStackSize); 90 StackIterator iter = frame->begin(); 91 iter.iterate(functor); 68 92 } 69 93 if (frames.isEmpty() && !emptyIsAllowed) { … … 76 100 } 77 101 102 class CreateScriptCallStackForConsoleFunctor { 103 public: 104 CreateScriptCallStackForConsoleFunctor(bool needToSkipAFrame, size_t remainingCapacity, Vector<ScriptCallFrame>& frames) 105 : m_needToSkipAFrame(needToSkipAFrame) 106 , m_remainingCapacityForFrameCapture(remainingCapacity) 107 , m_frames(frames) 108 { 109 } 110 111 StackIterator::Status operator()(StackIterator& iter) 112 { 113 if (m_needToSkipAFrame) { 114 m_needToSkipAFrame = false; 115 return StackIterator::Continue; 116 } 117 118 if (m_remainingCapacityForFrameCapture) { 119 // This early exit is necessary to maintain our old behaviour 120 // but the stack trace we produce now is complete and handles all 121 // ways in which code may be running 122 if (!iter->callee() && m_frames.size()) 123 return StackIterator::Done; 124 125 unsigned line; 126 unsigned column; 127 iter->computeLineAndColumn(line, column); 128 m_frames.append(ScriptCallFrame(iter->functionName(), iter->sourceURL(), line, column)); 129 130 m_remainingCapacityForFrameCapture--; 131 return StackIterator::Continue; 132 } 133 return StackIterator::Done; 134 } 135 136 private: 137 bool m_needToSkipAFrame; 138 size_t m_remainingCapacityForFrameCapture; 139 Vector<ScriptCallFrame>& m_frames; 140 }; 141 78 142 PassRefPtr<ScriptCallStack> createScriptCallStack(JSC::ExecState* exec, size_t maxStackSize) 79 143 { … … 82 146 CallFrame* frame = exec->vm().topCallFrame; 83 147 StackIterator iter = frame->begin(); 84 if (iter.numberOfFrames() > 1) 85 ++iter; 86 for (; iter != frame->end() && maxStackSize--; ++iter) { 87 // This early exit is necessary to maintain our old behaviour 88 // but the stack trace we produce now is complete and handles all 89 // ways in which code may be running 90 if (!iter->callee() && frames.size()) 91 break; 92 unsigned line; 93 unsigned column; 94 iter->computeLineAndColumn(line, column); 95 frames.append(ScriptCallFrame(iter->functionName(), iter->sourceURL(), line, column)); 96 } 148 size_t numberOfFrames = iter.numberOfFrames(); 149 CreateScriptCallStackForConsoleFunctor functor(numberOfFrames > 1, maxStackSize, frames); 150 iter.iterate(functor); 97 151 return ScriptCallStack::create(frames); 98 152 }
Note:
See TracChangeset
for help on using the changeset viewer.