blob: e5d69468e966d55a0d73ce969f033d3bbef4bb70 [file] [log] [blame]
/* -*- 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 "BaselineCompiler-shared.h"
#include "jit/BaselineIC.h"
#include "jit/VMFunctions.h"
using namespace js;
using namespace js::jit;
BaselineCompilerShared::BaselineCompilerShared(JSContext *cx, HandleScript script)
: cx(cx),
script(cx, script),
pc(script->code),
ionCompileable_(jit::IsIonEnabled(cx) && CanIonCompileScript(cx, script, false)),
ionOSRCompileable_(jit::IsIonEnabled(cx) && CanIonCompileScript(cx, script, true)),
debugMode_(cx->compartment()->debugMode()),
analysis_(script),
frame(cx, script, masm),
stubSpace_(),
icEntries_(),
pcMappingEntries_(),
icLoadLabels_(),
pushedBeforeCall_(0),
inCall_(false),
spsPushToggleOffset_()
{ }
bool
BaselineCompilerShared::callVM(const VMFunction &fun)
{
IonCompartment *ion = cx->compartment()->ionCompartment();
IonCode *code = ion->getVMWrapper(fun);
if (!code)
return false;
#ifdef DEBUG
// Assert prepareVMCall() has been called.
JS_ASSERT(inCall_);
inCall_ = false;
#endif
// Compute argument size. Note that this include the size of the frame pointer
// pushed by prepareVMCall.
uint32_t argSize = fun.explicitStackSlots() * sizeof(void *) + sizeof(void *);
// Assert all arguments were pushed.
JS_ASSERT(masm.framePushed() - pushedBeforeCall_ == argSize);
uint32_t frameSize = BaselineFrame::FramePointerOffset + BaselineFrame::Size() +
(frame.nlocals() + frame.stackDepth()) * sizeof(Value);
masm.store32(Imm32(frameSize), Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
uint32_t descriptor = MakeFrameDescriptor(frameSize + argSize, IonFrame_BaselineJS);
masm.push(Imm32(descriptor));
// Perform the call.
masm.call(code);
uint32_t callOffset = masm.currentOffset();
masm.pop(BaselineFrameReg);
// Add a fake ICEntry (without stubs), so that the return offset to
// pc mapping works.
ICEntry entry(pc - script->code, false);
entry.setReturnOffset(callOffset);
return icEntries_.append(entry);
}