~ubuntu-branches/ubuntu/saucy/mozjs17/saucy

« back to all changes in this revision

Viewing changes to js/src/methodjit/TrampolineCompiler.cpp

  • Committer: Package Import Robot
  • Author(s): Rico Tzschichholz
  • Date: 2013-05-25 12:24:23 UTC
  • Revision ID: package-import@ubuntu.com-20130525122423-zmxucrhtensw90xy
Tags: upstream-17.0.0
ImportĀ upstreamĀ versionĀ 17.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 
2
 * vim: set ts=4 sw=4 et tw=99:
 
3
 *
 
4
 * This Source Code Form is subject to the terms of the Mozilla Public
 
5
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 
6
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
7
 
 
8
#include "TrampolineCompiler.h"
 
9
#include "StubCalls.h"
 
10
#include "assembler/assembler/LinkBuffer.h"
 
11
#include "assembler/jit/ExecutableAllocator.h"
 
12
 
 
13
namespace js {
 
14
namespace mjit {
 
15
 
 
16
#define CHECK_RESULT(x) if (!(x)) return false
 
17
#define COMPILE(which, pool, how) CHECK_RESULT(compileTrampoline(&(which), &pool, how))
 
18
#define RELEASE(which, pool) JS_BEGIN_MACRO \
 
19
    which = NULL;                           \
 
20
    if (pool)                               \
 
21
        pool->release();                    \
 
22
    pool = NULL;                            \
 
23
JS_END_MACRO
 
24
 
 
25
typedef JSC::MacroAssembler::Address Address;
 
26
typedef JSC::MacroAssembler::Label Label;
 
27
typedef JSC::MacroAssembler::Jump Jump;
 
28
typedef JSC::MacroAssembler::ImmPtr ImmPtr;
 
29
typedef JSC::MacroAssembler::Imm32 Imm32;
 
30
typedef JSC::MacroAssembler::Address Address;
 
31
 
 
32
bool
 
33
TrampolineCompiler::compile()
 
34
{
 
35
#ifdef JS_METHODJIT_SPEW
 
36
    JMCheckLogging();
 
37
#endif
 
38
 
 
39
    COMPILE(trampolines->forceReturn, trampolines->forceReturnPool, generateForceReturn);
 
40
#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64)
 
41
    COMPILE(trampolines->forceReturnFast, trampolines->forceReturnFastPool, generateForceReturnFast);
 
42
#endif
 
43
 
 
44
    return true;
 
45
}
 
46
 
 
47
void
 
48
TrampolineCompiler::release(Trampolines *tramps)
 
49
{
 
50
    RELEASE(tramps->forceReturn, tramps->forceReturnPool);
 
51
#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64)
 
52
    RELEASE(tramps->forceReturnFast, tramps->forceReturnFastPool);
 
53
#endif
 
54
}
 
55
 
 
56
bool
 
57
TrampolineCompiler::compileTrampoline(Trampolines::TrampolinePtr *where,
 
58
                                      JSC::ExecutablePool **poolp, TrampolineGenerator generator)
 
59
{
 
60
    Assembler masm;
 
61
 
 
62
    Label entry = masm.label();
 
63
    CHECK_RESULT(generator(masm));
 
64
    JS_ASSERT(entry.isSet());
 
65
 
 
66
    bool ok;
 
67
    JSC::LinkBuffer buffer(&masm, execAlloc, poolp, &ok, JSC::METHOD_CODE);
 
68
    if (!ok)
 
69
        return false;
 
70
    masm.finalize(buffer);
 
71
    uint8_t *result = (uint8_t*)buffer.finalizeCodeAddendum().dataLocation();
 
72
    *where = JS_DATA_TO_FUNC_PTR(Trampolines::TrampolinePtr, result + masm.distanceOf(entry));
 
73
 
 
74
    return true;
 
75
}
 
76
 
 
77
/*
 
78
 * This is shamelessly copied from emitReturn, but with several changes:
 
79
 * - There was always at least one inline call.
 
80
 * - We don't know if there are activation objects or a script with nesting
 
81
 *   state whose active frames need adjustment, so we always stub the epilogue.
 
82
 * - We don't know where we came from, so we don't know frame depth or PC.
 
83
 * - There is no stub buffer.
 
84
 */
 
85
bool
 
86
TrampolineCompiler::generateForceReturn(Assembler &masm)
 
87
{
 
88
    /* The JSStackFrame register may have been clobbered while returning, reload it. */
 
89
    masm.loadPtr(FrameAddress(VMFrame::offsetOfFp), JSFrameReg);
 
90
 
 
91
    /* Perform the frame epilogue. */
 
92
    masm.fallibleVMCall(true, JS_FUNC_TO_DATA_PTR(void *, stubs::AnyFrameEpilogue), NULL, NULL, 0);
 
93
 
 
94
    /* Store any known return value */
 
95
    masm.loadValueAsComponents(UndefinedValue(), JSReturnReg_Type, JSReturnReg_Data);
 
96
    Jump rvalClear = masm.branchTest32(Assembler::Zero,
 
97
                                       FrameFlagsAddress(), Imm32(StackFrame::HAS_RVAL));
 
98
    Address rvalAddress(JSFrameReg, StackFrame::offsetOfReturnValue());
 
99
    masm.loadValueAsComponents(rvalAddress, JSReturnReg_Type, JSReturnReg_Data);
 
100
    rvalClear.linkTo(masm.label(), &masm);
 
101
 
 
102
    /* Return to the caller */
 
103
    masm.loadPtr(Address(JSFrameReg, StackFrame::offsetOfNcode()), Registers::ReturnReg);
 
104
    masm.jump(Registers::ReturnReg);
 
105
    return true;
 
106
}
 
107
 
 
108
#if (defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)) || defined(_WIN64)
 
109
bool
 
110
TrampolineCompiler::generateForceReturnFast(Assembler &masm)
 
111
{
 
112
#ifdef _WIN64
 
113
    masm.addPtr(Imm32(32), Registers::StackPointer);
 
114
#else
 
115
    // In case of no fast call, when we change the return address,
 
116
    // we need to make sure add esp by 8.
 
117
    masm.addPtr(Imm32(16), Registers::StackPointer);
 
118
#endif
 
119
    return generateForceReturn(masm);
 
120
}
 
121
#endif
 
122
 
 
123
} /* namespace mjit */
 
124
} /* namespace js */
 
125