/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2013, 2014 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include "config.h"
#include "CallFrame.h"
+#include "CallFrameInlines.h"
#include "CodeBlock.h"
#include "Interpreter.h"
+#include "JSActivation.h"
+#include "JSCInlines.h"
+#include "VMEntryScope.h"
+#include <wtf/StringPrintStream.h>
namespace JSC {
-JSValue CallFrame::thisValue()
+#ifndef NDEBUG
+JSStack* CallFrame::stack()
{
- return this[codeBlock()->thisRegister()].jsValue();
+ return &interpreter()->stack();
}
-#ifndef NDEBUG
-void CallFrame::dumpCaller()
+#endif
+
+#if USE(JSVALUE32_64)
+unsigned CallFrame::locationAsBytecodeOffset() const
+{
+ ASSERT(codeBlock());
+ ASSERT(hasLocationAsBytecodeOffset());
+ return currentVPC() - codeBlock()->instructions().begin();
+}
+
+void CallFrame::setLocationAsBytecodeOffset(unsigned offset)
{
- int signedLineNumber;
- intptr_t sourceID;
- UString urlString;
- JSValue function;
+ ASSERT(codeBlock());
+ setCurrentVPC(codeBlock()->instructions().begin() + offset);
+ ASSERT(hasLocationAsBytecodeOffset());
+}
+#else
+Instruction* CallFrame::currentVPC() const
+{
+ return codeBlock()->instructions().begin() + locationAsBytecodeOffset();
+}
+void CallFrame::setCurrentVPC(Instruction* vpc)
+{
+ setLocationAsBytecodeOffset(vpc - codeBlock()->instructions().begin());
+}
+#endif
- interpreter()->retrieveLastCaller(this, signedLineNumber, sourceID, urlString, function);
- printf("Callpoint => %s:%d\n", urlString.ascii(), signedLineNumber);
+#if ENABLE(DFG_JIT)
+unsigned CallFrame::bytecodeOffsetFromCodeOriginIndex()
+{
+ ASSERT(hasLocationAsCodeOriginIndex());
+ CodeBlock* codeBlock = this->codeBlock();
+ ASSERT(codeBlock);
+
+ CodeOrigin codeOrigin;
+ unsigned index = locationAsCodeOriginIndex();
+ ASSERT(codeBlock->canGetCodeOrigin(index));
+ codeOrigin = codeBlock->codeOrigin(index);
+
+ for (InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame; inlineCallFrame;) {
+ if (inlineCallFrame->baselineCodeBlock() == codeBlock)
+ return codeOrigin.bytecodeIndex;
+
+ codeOrigin = inlineCallFrame->caller;
+ inlineCallFrame = codeOrigin.inlineCallFrame;
+ }
+ return codeOrigin.bytecodeIndex;
}
+
+#endif // ENABLE(DFG_JIT)
+
+unsigned CallFrame::bytecodeOffset()
+{
+ if (!codeBlock())
+ return 0;
+#if ENABLE(DFG_JIT)
+ if (hasLocationAsCodeOriginIndex())
+ return bytecodeOffsetFromCodeOriginIndex();
#endif
+ return locationAsBytecodeOffset();
+}
+
+CodeOrigin CallFrame::codeOrigin()
+{
+ if (!codeBlock())
+ return CodeOrigin(0);
+#if ENABLE(DFG_JIT)
+ if (hasLocationAsCodeOriginIndex()) {
+ unsigned index = locationAsCodeOriginIndex();
+ ASSERT(codeBlock()->canGetCodeOrigin(index));
+ return codeBlock()->codeOrigin(index);
+ }
+#endif
+ return CodeOrigin(locationAsBytecodeOffset());
+}
+
+Register* CallFrame::topOfFrameInternal()
+{
+ CodeBlock* codeBlock = this->codeBlock();
+ ASSERT(codeBlock);
+ return registers() + codeBlock->stackPointerOffset();
+}
+
+JSGlobalObject* CallFrame::vmEntryGlobalObject()
+{
+ if (this == lexicalGlobalObject()->globalExec())
+ return lexicalGlobalObject();
+
+ // For any ExecState that's not a globalExec, the
+ // dynamic global object must be set since code is running
+ ASSERT(vm().entryScope);
+ return vm().entryScope->globalObject();
+}
+
+JSActivation* CallFrame::activation() const
+{
+ CodeBlock* codeBlock = this->codeBlock();
+ RELEASE_ASSERT(codeBlock->needsActivation());
+ VirtualRegister activationRegister = codeBlock->activationRegister();
+ return registers()[activationRegister.offset()].Register::activation();
+}
+
+void CallFrame::setActivation(JSActivation* activation)
+{
+ CodeBlock* codeBlock = this->codeBlock();
+ RELEASE_ASSERT(codeBlock->needsActivation());
+ VirtualRegister activationRegister = codeBlock->activationRegister();
+ registers()[activationRegister.offset()] = activation;
+}
+
+void CallFrame::dump(PrintStream& out)
+{
+ if (CodeBlock* codeBlock = this->codeBlock()) {
+ out.print(codeBlock->inferredName(), "#", codeBlock->hashAsStringIfPossible(), " [", codeBlock->jitType(), "]");
+
+ out.print("(");
+ thisValue().dumpForBacktrace(out);
+
+ for (size_t i = 0; i < argumentCount(); ++i) {
+ out.print(", ");
+ JSValue value = argument(i);
+ value.dumpForBacktrace(out);
+ }
+
+ out.print(")");
+ return;
+ }
+
+ out.print(returnPC());
}
+
+const char* CallFrame::describeFrame()
+{
+ const size_t bufferSize = 200;
+ static char buffer[bufferSize + 1];
+
+ WTF::StringPrintStream stringStream;
+
+ dump(stringStream);
+
+ strncpy(buffer, stringStream.toCString().data(), bufferSize);
+ buffer[bufferSize] = '\0';
+
+ return buffer;
+}
+
+} // namespace JSC