Added support for ISourcePawnEngine natives.
1 /* vim: set ts=4 sw=4 tw=99 et:
3 * Copyright (C) 2012 David Anderson
5 * This file is part of JITCraft.
7 * JITCraft is free software: you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License as published by the Free
9 * Software Foundation, either version 3 of the License, or (at your option)
12 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with
17 * JITCraft. If not, see http://www.gnu.org/licenses/.
41 buffer_ = (char *)malloc(STACK_SIZE);
45 top_.sp = reinterpret_cast<LocalSlot *>(buffer_);
48 end_ = buffer_ + STACK_SIZE;
52 InvokeArgs::~InvokeArgs()
54 stack_->popInvokeFrame(*this);
57 NativeArgs::~NativeArgs()
59 stack_->popNativeFrame(*this);
63 SizeForCodeFrame(Code *code)
65 return sizeof(Frame) + sizeof(LocalSlot) * (code->nlocals() + code->maxStackDepth());
69 Stack::pushInvokeFrame(Handle<Function> fun, InvokeArgs &args)
71 size_t nbytes = SizeForCodeFrame(fun->code()) +
72 sizeof(LocalSlot) * fun->nargs();
73 if (reinterpret_cast<char *>(top_.sp) + nbytes >= end_) {
78 memset(top_.sp, 0, sizeof(LocalSlot) * fun->nargs());
80 args.nargs_ = fun->nargs();
82 top_.sp += fun->nargs();
84 Frame *frame = reinterpret_cast<Frame *>(top_.sp);
85 new (frame) Frame(top_.fp, top_.pc, fun, fun->code(), ZONE()->heap().lifoPosition());
87 top_.pc = frame->code()->start();
88 top_.sp = frame->stackBase();
95 Stack::pushNativeFrame(Handle<Native> native, NativeArgs &args, unsigned argc)
97 size_t nbytes = sizeof(intptr_t) * argc + sizeof(Frame);
98 if (reinterpret_cast<char *>(top_.sp) + nbytes >= end_) {
103 memset(top_.sp, 0, sizeof(intptr_t) * argc);
104 args.argsBase_ = top_.sp;
106 top_.sp = reinterpret_cast<LocalSlot *>(reinterpret_cast<intptr_t *>(top_.sp) + argc);
108 Frame *frame = reinterpret_cast<Frame *>(top_.sp);
109 new (frame) Frame(top_.fp, top_.pc, native, ZONE()->heap().lifoPosition());
112 top_.sp = reinterpret_cast<LocalSlot *>(frame + 1);
119 Stack::pushInlineFrame(Handle<Function> fun)
121 Code *code = fun->code();
122 size_t nbytes = SizeForCodeFrame(code);
123 if (reinterpret_cast<char *>(top_.sp) + nbytes >= end_) {
128 Frame *frame = reinterpret_cast<Frame *>(top_.sp);
129 new (frame) Frame(top_.fp, top_.pc, fun, code, ZONE()->heap().lifoPosition());
130 memset(frame->locals(), 0, sizeof(LocalSlot) * code->nlocals());
132 top_.pc = frame->code()->start();
133 top_.sp = frame->stackBase();
141 Stack::popInlineFrame()
143 ZONE()->heap().unwindLifo(top_.fp->lifoPosition());
145 Frame *prev = top_.fp->prev();
146 Function *fun = top_.fp->maybeFun();
147 Code *code = top_.fp->code();
149 size_t nbytes = sizeof(LocalSlot) * code->nlocals() +
151 sizeof(LocalSlot) * (fun ? fun->nargs() : 0);
153 top_.pc = top_.fp->prevpc();
154 top_.sp = reinterpret_cast<LocalSlot *>(reinterpret_cast<char *>(top_.sp) - nbytes);
160 Stack::popInvokeFrame(InvokeArgs &args)
162 ZONE()->heap().unwindLifo(top_.fp->lifoPosition());
164 top_.pc = top_.fp->prevpc();
165 top_.sp = args.args_;
166 top_.fp = top_.fp->prev();
170 Stack::popNativeFrame(NativeArgs &args)
172 ZONE()->heap().unwindLifo(top_.fp->lifoPosition());
174 top_.pc = top_.fp->prevpc();
175 top_.sp = args.argsBase_;
176 top_.fp = top_.fp->prev();
180 Frame::accept(VirtualObjectVisitor *visitor)
182 visitor->visit(reinterpret_cast<Object **>(&callee_));
183 visitor->visit(reinterpret_cast<Object **>(&code_));
187 TraceFunctionFrame(VirtualObjectVisitor *visitor, Frame *fp, LocalSlot *sp, bytecode *pc)
189 Code *code = fp->code();
190 LocalSlot *slots = fp->locals();
192 // Trace local variables.
193 for (unsigned i = 0; i < code->nlocals(); i++) {
194 Type *type = code->localType(i);
195 if (type->isTraceable())
196 visitor->visit(&slots[i].obj);
199 // Trace arguments, if a function call. Note that this means we usually
200 // mark arguments twice, once on the caller side and once on the callee.
201 // This makes it easier to deal with invoke frames which have no caller.
202 if (Function *fun = fp->maybeFun()) {
203 for (unsigned i = 0; i < fun->nargs(); i++) {
204 Type *type = fun->argType(i);
205 if (type->isTraceable())
206 visitor->visit(&fp->arg(i).obj);
210 // Finally, trace stack slots. Not every gc-point in the bytecode will
211 // have a safepoint; since they are actually uncommon, we don't emit
212 // them unless at least one stack slot would be marked.
213 if (uint8 *safepoint = code->safepointAt(code->pcToOffset(pc))) {
214 LocalSlot *base = fp->stackBase();
215 unsigned stackDepth = unsigned(sp - fp->stackBase());
216 assert(stackDepth <= code->maxStackDepth());
218 for (unsigned i = 0; i < stackDepth; i++) {
219 if (safepoint[i / 8] & (1 << (i % 8)))
220 visitor->visit(&base[i].obj);
226 Stack::accept(VirtualObjectVisitor *visitor)
228 LocalSlot *sp = top_.sp;
229 bytecode *pc = top_.pc;
231 for (Frame *frame = top_.fp; frame; frame = frame->prev()) {
232 if (!frame->isNative())
233 TraceFunctionFrame(visitor, frame, sp, pc);
234 frame->accept(visitor);
236 sp = reinterpret_cast<LocalSlot *>(frame);
237 pc = frame->prevpc();
242 Stack::isInCallStack(Handle<Module> module)
244 for (Frame *frame = top_.fp; frame; frame = frame->prev()) {
245 if (frame->code()->module() == module)