1/* 2 * Copyright (C) 2008, 2013, 2014 Apple Inc. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "CallFrame.h" 28 29#include "CallFrameInlines.h" 30#include "CodeBlock.h" 31#include "Interpreter.h" 32#include "JSActivation.h" 33#include "JSCInlines.h" 34#include "VMEntryScope.h" 35#include <wtf/StringPrintStream.h> 36 37namespace JSC { 38 39#ifndef NDEBUG 40JSStack* CallFrame::stack() 41{ 42 return &interpreter()->stack(); 43} 44 45#endif 46 47#if USE(JSVALUE32_64) 48unsigned CallFrame::locationAsBytecodeOffset() const 49{ 50 ASSERT(codeBlock()); 51 ASSERT(hasLocationAsBytecodeOffset()); 52 return currentVPC() - codeBlock()->instructions().begin(); 53} 54 55void CallFrame::setLocationAsBytecodeOffset(unsigned offset) 56{ 57 ASSERT(codeBlock()); 58 setCurrentVPC(codeBlock()->instructions().begin() + offset); 59 ASSERT(hasLocationAsBytecodeOffset()); 60} 61#else 62Instruction* CallFrame::currentVPC() const 63{ 64 return codeBlock()->instructions().begin() + locationAsBytecodeOffset(); 65} 66void CallFrame::setCurrentVPC(Instruction* vpc) 67{ 68 setLocationAsBytecodeOffset(vpc - codeBlock()->instructions().begin()); 69} 70#endif 71 72#if ENABLE(DFG_JIT) 73unsigned CallFrame::bytecodeOffsetFromCodeOriginIndex() 74{ 75 ASSERT(hasLocationAsCodeOriginIndex()); 76 CodeBlock* codeBlock = this->codeBlock(); 77 ASSERT(codeBlock); 78 79 CodeOrigin codeOrigin; 80 unsigned index = locationAsCodeOriginIndex(); 81 ASSERT(codeBlock->canGetCodeOrigin(index)); 82 codeOrigin = codeBlock->codeOrigin(index); 83 84 for (InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame; inlineCallFrame;) { 85 if (inlineCallFrame->baselineCodeBlock() == codeBlock) 86 return codeOrigin.bytecodeIndex; 87 88 codeOrigin = inlineCallFrame->caller; 89 inlineCallFrame = codeOrigin.inlineCallFrame; 90 } 91 return codeOrigin.bytecodeIndex; 92} 93 94#endif // ENABLE(DFG_JIT) 95 96unsigned CallFrame::bytecodeOffset() 97{ 98 if (!codeBlock()) 99 return 0; 100#if ENABLE(DFG_JIT) 101 if (hasLocationAsCodeOriginIndex()) 102 return bytecodeOffsetFromCodeOriginIndex(); 103#endif 104 return locationAsBytecodeOffset(); 105} 106 107CodeOrigin CallFrame::codeOrigin() 108{ 109 if (!codeBlock()) 110 return CodeOrigin(0); 111#if ENABLE(DFG_JIT) 112 if (hasLocationAsCodeOriginIndex()) { 113 unsigned index = locationAsCodeOriginIndex(); 114 ASSERT(codeBlock()->canGetCodeOrigin(index)); 115 return codeBlock()->codeOrigin(index); 116 } 117#endif 118 return CodeOrigin(locationAsBytecodeOffset()); 119} 120 121Register* CallFrame::topOfFrameInternal() 122{ 123 CodeBlock* codeBlock = this->codeBlock(); 124 ASSERT(codeBlock); 125 return registers() + codeBlock->stackPointerOffset(); 126} 127 128JSGlobalObject* CallFrame::vmEntryGlobalObject() 129{ 130 if (this == lexicalGlobalObject()->globalExec()) 131 return lexicalGlobalObject(); 132 133 // For any ExecState that's not a globalExec, the 134 // dynamic global object must be set since code is running 135 ASSERT(vm().entryScope); 136 return vm().entryScope->globalObject(); 137} 138 139JSActivation* CallFrame::activation() const 140{ 141 CodeBlock* codeBlock = this->codeBlock(); 142 RELEASE_ASSERT(codeBlock->needsActivation()); 143 VirtualRegister activationRegister = codeBlock->activationRegister(); 144 return registers()[activationRegister.offset()].Register::activation(); 145} 146 147void CallFrame::setActivation(JSActivation* activation) 148{ 149 CodeBlock* codeBlock = this->codeBlock(); 150 RELEASE_ASSERT(codeBlock->needsActivation()); 151 VirtualRegister activationRegister = codeBlock->activationRegister(); 152 registers()[activationRegister.offset()] = activation; 153} 154 155void CallFrame::dump(PrintStream& out) 156{ 157 if (CodeBlock* codeBlock = this->codeBlock()) { 158 out.print(codeBlock->inferredName(), "#", codeBlock->hashAsStringIfPossible(), " [", codeBlock->jitType(), "]"); 159 160 out.print("("); 161 thisValue().dumpForBacktrace(out); 162 163 for (size_t i = 0; i < argumentCount(); ++i) { 164 out.print(", "); 165 JSValue value = argument(i); 166 value.dumpForBacktrace(out); 167 } 168 169 out.print(")"); 170 171 return; 172 } 173 174 out.print(returnPC()); 175} 176 177const char* CallFrame::describeFrame() 178{ 179 const size_t bufferSize = 200; 180 static char buffer[bufferSize + 1]; 181 182 WTF::StringPrintStream stringStream; 183 184 dump(stringStream); 185 186 strncpy(buffer, stringStream.toCString().data(), bufferSize); 187 buffer[bufferSize] = '\0'; 188 189 return buffer; 190} 191 192} // namespace JSC 193