Bug 1030446 - Move AsmJSFrameIterator to its own file (r=dougc)

This commit is contained in:
Luke Wagner 2014-06-25 14:26:03 -05:00
parent 49199e74fd
commit 543edaacc2
7 changed files with 155 additions and 124 deletions

View File

@ -0,0 +1,109 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "jit/AsmJSFrameIterator.h"
#include "jit/AsmJS.h"
#include "jit/AsmJSModule.h"
using namespace js;
using namespace js::jit;
static uint8_t *
ReturnAddressForExitCall(uint8_t **psp)
{
uint8_t *sp = *psp;
#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
// For calls to Ion/C++ on x86/x64, the exitSP is the SP right before the call
// to C++. Since the call instruction pushes the return address, we know
// that the return address is 1 word below exitSP.
return *(uint8_t**)(sp - sizeof(void*));
#elif defined(JS_CODEGEN_ARM)
// For calls to Ion/C++ on ARM, the *caller* pushes the return address on
// the stack. For Ion, this is just part of the ABI. For C++, the return
// address is explicitly pushed before the call since we cannot expect the
// callee to immediately push lr. This means that exitSP points to the
// return address.
return *(uint8_t**)sp;
#elif defined(JS_CODEGEN_MIPS)
// On MIPS we have two cases: an exit to C++ will store the return address
// at ShadowStackSpace above sp; an exit to Ion will store the return
// address at sp. To distinguish the two cases, the low bit of sp (which is
// aligned and therefore zero) is set for Ion exits.
if (uintptr_t(sp) & 0x1) {
sp = *psp -= 0x1; // Clear the low bit
return *(uint8_t**)sp;
}
return *(uint8_t**)(sp + ShadowStackSpace);
#else
# error "Unknown architecture!"
#endif
}
static uint8_t *
ReturnAddressForJitCall(uint8_t *sp)
{
// Once inside JIT code, sp always points to the word before the return
// address.
return *(uint8_t**)(sp - sizeof(void*));
}
AsmJSFrameIterator::AsmJSFrameIterator(const AsmJSActivation *activation)
: module_(nullptr)
{
if (!activation || activation->isInterruptedSP())
return;
module_ = &activation->module();
sp_ = activation->exitSP();
settle(ReturnAddressForExitCall(&sp_));
}
void
AsmJSFrameIterator::operator++()
{
settle(ReturnAddressForJitCall(sp_));
}
void
AsmJSFrameIterator::settle(uint8_t *returnAddress)
{
callsite_ = module_->lookupCallSite(returnAddress);
if (!callsite_ || callsite_->isEntry()) {
module_ = nullptr;
return;
}
if (callsite_->isEntry()) {
module_ = nullptr;
return;
}
sp_ += callsite_->stackDepth();
if (callsite_->isExit())
return settle(ReturnAddressForJitCall(sp_));
JS_ASSERT(callsite_->isNormal());
}
JSAtom *
AsmJSFrameIterator::functionDisplayAtom() const
{
JS_ASSERT(!done());
return module_->functionName(callsite_->functionNameIndex());
}
unsigned
AsmJSFrameIterator::computeLine(uint32_t *column) const
{
JS_ASSERT(!done());
if (column)
*column = callsite_->column();
return callsite_->line();
}

View File

@ -0,0 +1,41 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jit_AsmJSFrameIterator_h
#define jit_AsmJSFrameIterator_h
#include "mozilla/NullPtr.h"
#include <stdint.h>
class JSAtom;
namespace js {
class AsmJSActivation;
class AsmJSModule;
namespace jit { struct CallSite; }
// Iterates over the frames of a single AsmJSActivation.
class AsmJSFrameIterator
{
const AsmJSModule *module_;
const jit::CallSite *callsite_;
uint8_t *sp_;
void settle(uint8_t *returnAddress);
public:
explicit AsmJSFrameIterator(const AsmJSActivation *activation);
void operator++();
bool done() const { return !module_; }
JSAtom *functionDisplayAtom() const;
unsigned computeLine(uint32_t *column) const;
};
} // namespace js
#endif // jit_AsmJSFrameIterator_h

View File

@ -34,101 +34,6 @@ using namespace js::jit;
using mozilla::IsNaN;
using mozilla::PodZero;
static uint8_t *
ReturnAddressForExitCall(uint8_t **psp)
{
uint8_t *sp = *psp;
#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
// For calls to Ion/C++ on x86/x64, the exitSP is the SP right before the call
// to C++. Since the call instruction pushes the return address, we know
// that the return address is 1 word below exitSP.
return *(uint8_t**)(sp - sizeof(void*));
#elif defined(JS_CODEGEN_ARM)
// For calls to Ion/C++ on ARM, the *caller* pushes the return address on
// the stack. For Ion, this is just part of the ABI. For C++, the return
// address is explicitly pushed before the call since we cannot expect the
// callee to immediately push lr. This means that exitSP points to the
// return address.
return *(uint8_t**)sp;
#elif defined(JS_CODEGEN_MIPS)
// On MIPS we have two cases: an exit to C++ will store the return address
// at ShadowStackSpace above sp; an exit to Ion will store the return
// address at sp. To distinguish the two cases, the low bit of sp (which is
// aligned and therefore zero) is set for Ion exits.
if (uintptr_t(sp) & 0x1) {
sp = *psp -= 0x1; // Clear the low bit
return *(uint8_t**)sp;
}
return *(uint8_t**)(sp + ShadowStackSpace);
#else
# error "Unknown architecture!"
#endif
}
static uint8_t *
ReturnAddressForJitCall(uint8_t *sp)
{
// Once inside JIT code, sp always points to the word before the return
// address.
return *(uint8_t**)(sp - sizeof(void*));
}
AsmJSFrameIterator::AsmJSFrameIterator(const AsmJSActivation *activation)
: module_(nullptr)
{
if (!activation || activation->isInterruptedSP())
return;
module_ = &activation->module();
sp_ = activation->exitSP();
settle(ReturnAddressForExitCall(&sp_));
}
void
AsmJSFrameIterator::operator++()
{
settle(ReturnAddressForJitCall(sp_));
}
void
AsmJSFrameIterator::settle(uint8_t *returnAddress)
{
callsite_ = module_->lookupCallSite(returnAddress);
if (!callsite_ || callsite_->isEntry()) {
module_ = nullptr;
return;
}
if (callsite_->isEntry()) {
module_ = nullptr;
return;
}
sp_ += callsite_->stackDepth();
if (callsite_->isExit())
return settle(ReturnAddressForJitCall(sp_));
JS_ASSERT(callsite_->isNormal());
}
JSAtom *
AsmJSFrameIterator::functionDisplayAtom() const
{
JS_ASSERT(!done());
return module_->functionName(callsite_->functionNameIndex());
}
unsigned
AsmJSFrameIterator::computeLine(uint32_t *column) const
{
JS_ASSERT(!done());
if (column)
*column = callsite_->column();
return callsite_->line();
}
static bool
CloneModule(JSContext *cx, MutableHandle<AsmJSModuleObject*> moduleObj)
{

View File

@ -9,31 +9,8 @@
#include "NamespaceImports.h"
class JSAtom;
namespace js {
class AsmJSActivation;
class AsmJSModule;
namespace jit { struct CallSite; }
// Iterates over the frames of a single AsmJSActivation.
class AsmJSFrameIterator
{
const AsmJSModule *module_;
const jit::CallSite *callsite_;
uint8_t *sp_;
void settle(uint8_t *returnAddress);
public:
explicit AsmJSFrameIterator(const AsmJSActivation *activation);
void operator++();
bool done() const { return !module_; }
JSAtom *functionDisplayAtom() const;
unsigned computeLine(uint32_t *column) const;
};
#ifdef JS_ION
// Create a new JSFunction to replace originalFun as the representation of the

View File

@ -54,8 +54,6 @@ using namespace js::frontend;
using mozilla::ArrayLength;
using mozilla::PodCopy;
using mozilla::Range;
using mozilla::RangedPtr;
static bool
fun_getProperty(JSContext *cx, HandleObject obj_, HandleId id, MutableHandleValue vp)
@ -765,7 +763,7 @@ js::FindBody(JSContext *cx, HandleFunction fun, HandleLinearString src, size_t *
if (!stableChars.initTwoByte(cx, src))
return false;
const Range<const jschar> srcChars = stableChars.twoByteRange();
const mozilla::Range<const jschar> srcChars = stableChars.twoByteRange();
TokenStream ts(cx, options, srcChars.start().get(), srcChars.length(), nullptr);
int nest = 0;
bool onward = true;
@ -801,7 +799,7 @@ js::FindBody(JSContext *cx, HandleFunction fun, HandleLinearString src, size_t *
*bodyStart = ts.currentToken().pos.begin;
if (braced)
*bodyStart += 1;
RangedPtr<const jschar> end = srcChars.end();
mozilla::RangedPtr<const jschar> end = srcChars.end();
if (end[-1] == '}') {
end--;
} else {
@ -1741,7 +1739,7 @@ FunctionConstructor(JSContext *cx, unsigned argc, Value *vp, GeneratorKind gener
if (!stableChars.initTwoByte(cx, str))
return false;
Range<const jschar> chars = stableChars.twoByteRange();
mozilla::Range<const jschar> chars = stableChars.twoByteRange();
SourceBufferHolder::Ownership ownership = stableChars.maybeGiveOwnershipToCaller()
? SourceBufferHolder::GiveOwnership
: SourceBufferHolder::NoOwnership;

View File

@ -247,6 +247,7 @@ if CONFIG['ENABLE_ION']:
'irregexp/NativeRegExpMacroAssembler.cpp',
'jit/AliasAnalysis.cpp',
'jit/AsmJS.cpp',
'jit/AsmJSFrameIterator.cpp',
'jit/AsmJSLink.cpp',
'jit/AsmJSModule.cpp',
'jit/AsmJSSignalHandlers.cpp',

View File

@ -12,7 +12,7 @@
#include "jsfun.h"
#include "jsscript.h"
#include "jit/AsmJSLink.h"
#include "jit/AsmJSFrameIterator.h"
#include "jit/JitFrameIterator.h"
#ifdef CHECK_OSIPOINT_REGISTERS
#include "jit/Registers.h" // for RegisterDump