mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-08 20:47:44 +00:00
Bug 1030446 - Move AsmJSFrameIterator to its own file (r=dougc)
This commit is contained in:
parent
49199e74fd
commit
543edaacc2
109
js/src/jit/AsmJSFrameIterator.cpp
Normal file
109
js/src/jit/AsmJSFrameIterator.cpp
Normal 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();
|
||||
}
|
||||
|
41
js/src/jit/AsmJSFrameIterator.h
Normal file
41
js/src/jit/AsmJSFrameIterator.h
Normal 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
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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',
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user