|
asherkin@263
|
1 |
/* vim: set ts=4 sw=4 tw=99 et: |
|
asherkin@263
|
2 |
* |
|
asherkin@263
|
3 |
* Copyright (C) 2012 David Anderson |
|
asherkin@263
|
4 |
* |
|
asherkin@263
|
5 |
* This file is part of JITCraft. |
|
asherkin@263
|
6 |
* |
|
asherkin@263
|
7 |
* JITCraft is free software: you can redistribute it and/or modify it under |
|
asherkin@263
|
8 |
* the terms of the GNU General Public License as published by the Free |
|
asherkin@263
|
9 |
* Software Foundation, either version 3 of the License, or (at your option) |
|
asherkin@263
|
10 |
* any later version. |
|
asherkin@263
|
11 |
* |
|
asherkin@263
|
12 |
* Foobar is distributed in the hope that it will be useful, but WITHOUT ANY |
|
asherkin@263
|
13 |
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
|
asherkin@263
|
14 |
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
|
asherkin@263
|
15 |
* |
|
asherkin@263
|
16 |
* You should have received a copy of the GNU General Public License along with |
|
asherkin@263
|
17 |
* JITCraft. If not, see http://www.gnu.org/licenses/. |
|
asherkin@263
|
18 |
*/ |
|
asherkin@263
|
19 |
#include <stdlib.h> |
|
asherkin@263
|
20 |
#include <string.h> |
|
asherkin@263
|
21 |
#include "../Utility.h" |
|
asherkin@263
|
22 |
#include "../Types.h" |
|
asherkin@263
|
23 |
#include "../Zone.h" |
|
asherkin@263
|
24 |
#include "../Strings.h" |
|
asherkin@263
|
25 |
#include "../Zone.h" |
|
asherkin@263
|
26 |
#include "BytecodeEmitter.h" |
|
asherkin@263
|
27 |
#include "Symbols.h" |
|
asherkin@263
|
28 |
#include "Scopes.h" |
|
asherkin@263
|
29 |
#include "../Spaces-inl.h" |
|
asherkin@263
|
30 |
#include "../Heap-inl.h" |
|
asherkin@263
|
31 |
|
|
asherkin@263
|
32 |
using namespace ke; |
|
asherkin@263
|
33 |
|
|
asherkin@263
|
34 |
StringTable::StringTable() |
|
asherkin@263
|
35 |
: set_(ZoneAllocatorPolicy()), |
|
asherkin@263
|
36 |
initialized_(false) |
|
asherkin@263
|
37 |
{ |
|
asherkin@263
|
38 |
} |
|
asherkin@263
|
39 |
|
|
asherkin@263
|
40 |
bool |
|
asherkin@263
|
41 |
StringTable::initialize() |
|
asherkin@263
|
42 |
{ |
|
asherkin@263
|
43 |
assert(!initialized_); |
|
asherkin@263
|
44 |
initialized_ = true; |
|
asherkin@263
|
45 |
if (!set_.init(16)) |
|
asherkin@263
|
46 |
return false; |
|
asherkin@263
|
47 |
return true; |
|
asherkin@263
|
48 |
} |
|
asherkin@263
|
49 |
|
|
asherkin@263
|
50 |
bool |
|
asherkin@263
|
51 |
StringTable::add(Handle<String> name, unsigned *indexp) |
|
asherkin@263
|
52 |
{ |
|
asherkin@263
|
53 |
if (!initialized_ && !initialize()) |
|
asherkin@263
|
54 |
return false; |
|
asherkin@263
|
55 |
|
|
asherkin@263
|
56 |
Set::Insert p = set_.findForAdd(*name); |
|
asherkin@263
|
57 |
if (p.found()) { |
|
asherkin@263
|
58 |
*indexp = p->index; |
|
asherkin@263
|
59 |
return true; |
|
asherkin@263
|
60 |
} |
|
asherkin@263
|
61 |
|
|
asherkin@263
|
62 |
if (strings_.length() > INT_MAX) { |
|
asherkin@263
|
63 |
ZONE()->reportAllocationOverflow(); |
|
asherkin@263
|
64 |
return false; |
|
asherkin@263
|
65 |
} |
|
asherkin@263
|
66 |
|
|
asherkin@263
|
67 |
Entry e(name, strings_.length()); |
|
asherkin@263
|
68 |
if (!strings_.append(e)) |
|
asherkin@263
|
69 |
return false; |
|
asherkin@263
|
70 |
|
|
asherkin@263
|
71 |
if (!set_.add(p, e)) |
|
asherkin@263
|
72 |
return false; |
|
asherkin@263
|
73 |
|
|
asherkin@263
|
74 |
*indexp = e.index; |
|
asherkin@263
|
75 |
|
|
asherkin@263
|
76 |
return true; |
|
asherkin@263
|
77 |
} |
|
asherkin@263
|
78 |
|
|
asherkin@263
|
79 |
void |
|
asherkin@263
|
80 |
StringTable::accept(VirtualObjectVisitor *visitor) |
|
asherkin@263
|
81 |
{ |
|
asherkin@263
|
82 |
for (size_t i = 0; i < strings_.length(); i++) |
|
asherkin@263
|
83 |
visitor->visit(reinterpret_cast<Object **>(&strings_[i].string)); |
|
asherkin@263
|
84 |
} |
|
asherkin@263
|
85 |
|
|
asherkin@263
|
86 |
BytecodeEmitter::BytecodeEmitter() |
|
asherkin@263
|
87 |
: AutoRooted(ZONE()), |
|
asherkin@263
|
88 |
buffer_(inline_buffer_), |
|
asherkin@263
|
89 |
buffer_pos_(buffer_), |
|
asherkin@263
|
90 |
buffer_end_(buffer_pos_ + ARRAY_LENGTH(inline_buffer_)), |
|
asherkin@263
|
91 |
oom_(false), |
|
asherkin@263
|
92 |
maxStackDepth_(0), |
|
asherkin@263
|
93 |
loopDepth_(0), |
|
asherkin@263
|
94 |
maxLoopDepth_(0) |
|
asherkin@263
|
95 |
{ |
|
asherkin@263
|
96 |
lastCodePosition_ = 0; |
|
asherkin@263
|
97 |
firstLine_ = 1; |
|
asherkin@263
|
98 |
} |
|
asherkin@263
|
99 |
|
|
asherkin@263
|
100 |
BytecodeEmitter::~BytecodeEmitter() |
|
asherkin@263
|
101 |
{ |
|
asherkin@263
|
102 |
for (size_t i = 0; i < oopRecords_.length(); i++) |
|
asherkin@263
|
103 |
delete oopRecords_[i]; |
|
asherkin@263
|
104 |
} |
|
asherkin@263
|
105 |
|
|
asherkin@263
|
106 |
void |
|
asherkin@263
|
107 |
BytecodeEmitter::accept(VirtualObjectVisitor *visitor) |
|
asherkin@263
|
108 |
{ |
|
asherkin@263
|
109 |
for (size_t i = 0; i < objects_.length(); i++) |
|
asherkin@263
|
110 |
visitor->visit(&objects_[i]); |
|
asherkin@263
|
111 |
|
|
asherkin@263
|
112 |
strings_.accept(visitor); |
|
asherkin@263
|
113 |
} |
|
asherkin@263
|
114 |
|
|
asherkin@263
|
115 |
bool |
|
asherkin@263
|
116 |
BytecodeEmitter::growBuffer(size_t nbytes) |
|
asherkin@263
|
117 |
{ |
|
asherkin@263
|
118 |
if (oom_) { |
|
asherkin@263
|
119 |
buffer_pos_ = buffer_; |
|
asherkin@263
|
120 |
return false; |
|
asherkin@263
|
121 |
} |
|
asherkin@263
|
122 |
|
|
asherkin@263
|
123 |
size_t newSize = size_t((buffer_end_ - buffer_) * 2); |
|
asherkin@263
|
124 |
if (newSize >= MAX_LENGTH) { |
|
asherkin@263
|
125 |
oom_ = true; |
|
asherkin@263
|
126 |
buffer_pos_ = buffer_; |
|
asherkin@263
|
127 |
ZONE()->reportOutOfMemory(); |
|
asherkin@263
|
128 |
return false; |
|
asherkin@263
|
129 |
} |
|
asherkin@263
|
130 |
|
|
asherkin@263
|
131 |
bytecode *newBuffer; |
|
asherkin@263
|
132 |
if (buffer_ == inline_buffer_) |
|
asherkin@263
|
133 |
newBuffer = (bytecode *)malloc(newSize); |
|
asherkin@263
|
134 |
else |
|
asherkin@263
|
135 |
newBuffer = (bytecode *)realloc(buffer_, newSize); |
|
asherkin@263
|
136 |
|
|
asherkin@263
|
137 |
// If we can't allocate a buffer, reset the buffer to the start and set |
|
asherkin@263
|
138 |
// a flag to indicate out-of-memory. |
|
asherkin@263
|
139 |
if (!newBuffer) { |
|
asherkin@263
|
140 |
oom_ = true; |
|
asherkin@263
|
141 |
buffer_pos_ = buffer_; |
|
asherkin@263
|
142 |
ZONE()->reportOutOfMemory(); |
|
asherkin@263
|
143 |
return false; |
|
asherkin@263
|
144 |
} |
|
asherkin@263
|
145 |
|
|
asherkin@263
|
146 |
if (buffer_ == inline_buffer_) |
|
asherkin@263
|
147 |
memcpy(newBuffer, inline_buffer_, (buffer_pos_ - inline_buffer_)); |
|
asherkin@263
|
148 |
|
|
asherkin@263
|
149 |
buffer_pos_ = newBuffer + size_t(buffer_pos_ - buffer_); |
|
asherkin@263
|
150 |
buffer_ = newBuffer; |
|
asherkin@263
|
151 |
buffer_end_ = buffer_ + newSize; |
|
asherkin@263
|
152 |
assert(buffer_pos_ + nbytes < buffer_end_); |
|
asherkin@263
|
153 |
|
|
asherkin@263
|
154 |
return true; |
|
asherkin@263
|
155 |
} |
|
asherkin@263
|
156 |
|
|
asherkin@263
|
157 |
void |
|
asherkin@263
|
158 |
BytecodeEmitter::recordOops() |
|
asherkin@263
|
159 |
{ |
|
asherkin@263
|
160 |
OopRecord *record = new OopRecord(oopMap_.length(), position()); |
|
asherkin@263
|
161 |
|
|
asherkin@263
|
162 |
if (!record->slots.ensure(record->depth)) { |
|
asherkin@263
|
163 |
oom_ = true; |
|
asherkin@263
|
164 |
return; |
|
asherkin@263
|
165 |
} |
|
asherkin@263
|
166 |
|
|
asherkin@263
|
167 |
bool hadOops = false; |
|
asherkin@263
|
168 |
for (size_t i = 0; i < oopMap_.length(); i++) { |
|
asherkin@263
|
169 |
bool bit = oopMap_[i]; |
|
asherkin@263
|
170 |
record->slots.infallibleAppend(bit); |
|
asherkin@263
|
171 |
hadOops |= bit; |
|
asherkin@263
|
172 |
} |
|
asherkin@263
|
173 |
|
|
asherkin@263
|
174 |
if (!hadOops) { |
|
asherkin@263
|
175 |
delete record; |
|
asherkin@263
|
176 |
return; |
|
asherkin@263
|
177 |
} |
|
asherkin@263
|
178 |
|
|
asherkin@263
|
179 |
oom_ &= oopRecords_.append(record); |
|
asherkin@263
|
180 |
} |
|
asherkin@263
|
181 |
|
|
asherkin@263
|
182 |
void |
|
asherkin@263
|
183 |
BytecodeEmitter::note_position(const SourcePosition &pos) |
|
asherkin@263
|
184 |
{ |
|
asherkin@263
|
185 |
assert(pos.line > 0); |
|
asherkin@263
|
186 |
assert(unsigned(pos.line) >= firstLine_); |
|
asherkin@263
|
187 |
|
|
asherkin@263
|
188 |
unsigned lineDelta = unsigned(pos.line) - firstLine_; |
|
asherkin@263
|
189 |
unsigned pcDelta = unsigned(position()) - lastCodePosition_; |
|
asherkin@263
|
190 |
|
|
asherkin@263
|
191 |
sourcemap_.writeUint32(pcDelta); |
|
asherkin@263
|
192 |
sourcemap_.writeUint32(lineDelta); |
|
asherkin@263
|
193 |
sourcemap_.writeUint32(pos.col); |
|
asherkin@263
|
194 |
|
|
asherkin@263
|
195 |
lastCodePosition_ = unsigned(position()); |
|
asherkin@263
|
196 |
} |
|
asherkin@263
|
197 |
|
|
asherkin@263
|
198 |
void |
|
asherkin@263
|
199 |
BytecodeEmitter::getglobal(Symbol *sym) |
|
asherkin@263
|
200 |
{ |
|
asherkin@263
|
201 |
ensure(OP_GETGLOBAL_LENGTH); |
|
asherkin@263
|
202 |
writeOp(OP_GETGLOBAL); |
|
asherkin@263
|
203 |
writeUint32(addString(sym->name())); |
|
asherkin@263
|
204 |
if (sym->type()->isTraceable()) |
|
asherkin@263
|
205 |
markOop(1); |
|
asherkin@263
|
206 |
} |
|
asherkin@263
|
207 |
void |
|
asherkin@263
|
208 |
BytecodeEmitter::setglobal(Symbol *sym) |
|
asherkin@263
|
209 |
{ |
|
asherkin@263
|
210 |
ensure(OP_SETGLOBAL_LENGTH); |
|
asherkin@263
|
211 |
writeOp(OP_SETGLOBAL); |
|
asherkin@263
|
212 |
writeUint32(addString(sym->name())); |
|
asherkin@263
|
213 |
if (sym->type()->isTraceable()) |
|
asherkin@263
|
214 |
markOop(1); |
|
asherkin@263
|
215 |
} |
|
asherkin@263
|
216 |
|
|
asherkin@263
|
217 |
void |
|
asherkin@263
|
218 |
BytecodeEmitter::getlocal(VariableSymbol *var) |
|
asherkin@263
|
219 |
{ |
|
asherkin@263
|
220 |
assert(var->storage() == VariableSymbol::Local); |
|
asherkin@263
|
221 |
ensure(OP_GETLOCAL_LENGTH); |
|
asherkin@263
|
222 |
writeOp(OP_GETLOCAL); |
|
asherkin@263
|
223 |
writeUint32(var->slot()); |
|
asherkin@263
|
224 |
if (var->type()->isTraceable()) |
|
asherkin@263
|
225 |
markOop(1); |
|
asherkin@263
|
226 |
} |
|
asherkin@263
|
227 |
|
|
asherkin@263
|
228 |
void |
|
asherkin@263
|
229 |
BytecodeEmitter::setlocal(VariableSymbol *var) |
|
asherkin@263
|
230 |
{ |
|
asherkin@263
|
231 |
assert(var->storage() == VariableSymbol::Local); |
|
asherkin@263
|
232 |
ensure(OP_SETLOCAL_LENGTH); |
|
asherkin@263
|
233 |
writeOp(OP_SETLOCAL); |
|
asherkin@263
|
234 |
writeUint32(var->slot()); |
|
asherkin@263
|
235 |
if (var->type()->isTraceable()) |
|
asherkin@263
|
236 |
markOop(1); |
|
asherkin@263
|
237 |
} |
|
asherkin@263
|
238 |
|
|
asherkin@263
|
239 |
void |
|
asherkin@263
|
240 |
BytecodeEmitter::getarg(VariableSymbol *var) |
|
asherkin@263
|
241 |
{ |
|
asherkin@263
|
242 |
assert(var->storage() == VariableSymbol::Arg); |
|
asherkin@263
|
243 |
ensure(OP_GETARG_LENGTH); |
|
asherkin@263
|
244 |
writeOp(OP_GETARG); |
|
asherkin@263
|
245 |
writeUint32(var->slot()); |
|
asherkin@263
|
246 |
if (var->type()->isTraceable()) |
|
asherkin@263
|
247 |
markOop(1); |
|
asherkin@263
|
248 |
} |
|
asherkin@263
|
249 |
|
|
asherkin@263
|
250 |
void |
|
asherkin@263
|
251 |
BytecodeEmitter::setarg(VariableSymbol *var) |
|
asherkin@263
|
252 |
{ |
|
asherkin@263
|
253 |
assert(var->storage() == VariableSymbol::Arg); |
|
asherkin@263
|
254 |
ensure(OP_SETARG_LENGTH); |
|
asherkin@263
|
255 |
writeOp(OP_SETARG); |
|
asherkin@263
|
256 |
writeUint32(var->slot()); |
|
asherkin@263
|
257 |
if (var->type()->isTraceable()) |
|
asherkin@263
|
258 |
markOop(1); |
|
asherkin@263
|
259 |
} |
|
asherkin@263
|
260 |
|
|
asherkin@263
|
261 |
bool |
|
asherkin@263
|
262 |
BytecodeEmitter::allocate(VariableSymbol *sym) |
|
asherkin@263
|
263 |
{ |
|
asherkin@263
|
264 |
assert(sym->isVariable()); |
|
asherkin@263
|
265 |
assert(sym->scope()->kind() == Scope::BLOCK); |
|
asherkin@263
|
266 |
|
|
asherkin@263
|
267 |
switch (sym->scope()->kind()) { |
|
asherkin@263
|
268 |
case Scope::BLOCK: |
|
asherkin@263
|
269 |
{ |
|
asherkin@263
|
270 |
// See overall comment on overflows. |
|
asherkin@263
|
271 |
assert(locals_.length() < UINT_MAX); |
|
asherkin@263
|
272 |
sym->allocate(VariableSymbol::Local, locals_.length()); |
|
asherkin@263
|
273 |
if (!locals_.append(sym)) |
|
asherkin@263
|
274 |
return false; |
|
asherkin@263
|
275 |
break; |
|
asherkin@263
|
276 |
} |
|
asherkin@263
|
277 |
|
|
asherkin@263
|
278 |
default: |
|
asherkin@263
|
279 |
assert(false); |
|
asherkin@263
|
280 |
return false; |
|
asherkin@263
|
281 |
} |
|
asherkin@263
|
282 |
|
|
asherkin@263
|
283 |
return true; |
|
asherkin@263
|
284 |
} |
|
asherkin@263
|
285 |
|
|
asherkin@263
|
286 |
void |
|
asherkin@263
|
287 |
BytecodeEmitter::newref(VariableSymbol *var) |
|
asherkin@263
|
288 |
{ |
|
asherkin@263
|
289 |
recordOops(); |
|
asherkin@263
|
290 |
if (var->storage() == VariableSymbol::Local) { |
|
asherkin@263
|
291 |
ensure(OP_VARREF_LIFO_LENGTH); |
|
asherkin@263
|
292 |
writeOp(OP_VARREF_LIFO); |
|
asherkin@263
|
293 |
} else { |
|
asherkin@263
|
294 |
assert(var->storage() == VariableSymbol::Arg); |
|
asherkin@263
|
295 |
ensure(OP_ARGREF_LIFO_LENGTH); |
|
asherkin@263
|
296 |
writeOp(OP_ARGREF_LIFO); |
|
asherkin@263
|
297 |
} |
|
asherkin@263
|
298 |
writeUint32(var->slot()); |
|
asherkin@263
|
299 |
markOop(1); |
|
asherkin@263
|
300 |
} |
|
asherkin@263
|
301 |
|
|
asherkin@263
|
302 |
Code * |
|
asherkin@263
|
303 |
BytecodeEmitter::finish() |
|
asherkin@263
|
304 |
{ |
|
asherkin@263
|
305 |
stop(); |
|
asherkin@263
|
306 |
|
|
asherkin@263
|
307 |
Zone *zone = ZONE(); |
|
asherkin@263
|
308 |
if (oom() || zone->hasPendingException()) |
|
asherkin@263
|
309 |
return NULL; |
|
asherkin@263
|
310 |
|
|
asherkin@263
|
311 |
Local<ByteArray> bytes(zone, ByteArray::New(zone, length(), Heap::Tenure_Old)); |
|
asherkin@263
|
312 |
if (!bytes) |
|
asherkin@263
|
313 |
return NULL; |
|
asherkin@263
|
314 |
memcpy(bytes->raw(), buffer(), length()); |
|
asherkin@263
|
315 |
|
|
asherkin@263
|
316 |
Local<FixedArray> objects(zone, FixedArray::New(zone, objects_.length(), Heap::Tenure_Old)); |
|
asherkin@263
|
317 |
if (!objects) |
|
asherkin@263
|
318 |
return NULL; |
|
asherkin@263
|
319 |
|
|
asherkin@263
|
320 |
for (size_t i = 0; i < objects_.length(); i++) |
|
asherkin@263
|
321 |
objects->set(zone, i, objects_[i]); |
|
asherkin@263
|
322 |
|
|
asherkin@263
|
323 |
// If any stack slots hold gc pointers at potential failure points in the |
|
asherkin@263
|
324 |
// bytecode, record them now. We do this by building a list of tuples; |
|
asherkin@263
|
325 |
// each tuple contains the pc offset, and a bitset containing which stack |
|
asherkin@263
|
326 |
// slots must be scanned by the gc. |
|
asherkin@263
|
327 |
Local<ByteArray> safepoints(zone); |
|
asherkin@263
|
328 |
if (oopRecords_.length()) { |
|
asherkin@263
|
329 |
size_t bytesPerSafepoint = Code::BytesPerSafepoint(maxStackDepth()); |
|
asherkin@263
|
330 |
size_t gcmapSize = bytesPerSafepoint * oopRecords_.length(); |
|
asherkin@263
|
331 |
safepoints = ByteArray::New(zone, gcmapSize, Heap::Tenure_Old); |
|
asherkin@263
|
332 |
if (!safepoints) |
|
asherkin@263
|
333 |
return NULL; |
|
asherkin@263
|
334 |
|
|
asherkin@263
|
335 |
Address cursor = safepoints->raw(); |
|
asherkin@263
|
336 |
for (size_t i = 0; i < oopRecords_.length(); i++) { |
|
asherkin@263
|
337 |
OopRecord *record = oopRecords_[i]; |
|
asherkin@263
|
338 |
assert(record->depth <= maxStackDepth()); |
|
asherkin@263
|
339 |
|
|
asherkin@263
|
340 |
*reinterpret_cast<unsigned *>(cursor) = record->offset; |
|
asherkin@263
|
341 |
|
|
asherkin@263
|
342 |
unsigned char *bits = reinterpret_cast<unsigned char *>(cursor + sizeof(unsigned)); |
|
asherkin@263
|
343 |
for (unsigned i = 0; i < record->depth; i++) |
|
asherkin@263
|
344 |
bits[i / 8] |= (1 << (i % 8)); |
|
asherkin@263
|
345 |
|
|
asherkin@263
|
346 |
cursor += bytesPerSafepoint; |
|
asherkin@263
|
347 |
} |
|
asherkin@263
|
348 |
|
|
asherkin@263
|
349 |
assert(cursor == safepoints->raw() + gcmapSize); |
|
asherkin@263
|
350 |
} |
|
asherkin@263
|
351 |
|
|
asherkin@263
|
352 |
Local<ByteArray> sourcemap(zone); |
|
asherkin@263
|
353 |
if (sourcemap_.length()) { |
|
asherkin@263
|
354 |
sourcemap = ByteArray::New(zone, sourcemap_.length(), Heap::Tenure_Old); |
|
asherkin@263
|
355 |
if (!sourcemap) |
|
asherkin@263
|
356 |
return NULL; |
|
asherkin@263
|
357 |
|
|
asherkin@263
|
358 |
memcpy(sourcemap->raw(), sourcemap_.buffer(), sourcemap_.length()); |
|
asherkin@263
|
359 |
} |
|
asherkin@263
|
360 |
|
|
asherkin@263
|
361 |
Local<FixedArray> strings(zone, FixedArray::New(zone, strings_.stringCount(), Heap::Tenure_Old)); |
|
asherkin@263
|
362 |
if (!strings) |
|
asherkin@263
|
363 |
return NULL; |
|
asherkin@263
|
364 |
for (size_t i = 0; i < strings_.stringCount(); i++) |
|
asherkin@263
|
365 |
strings->set(zone, i, strings_.stringAt(i)); |
|
asherkin@263
|
366 |
|
|
asherkin@263
|
367 |
Local<FixedArray> locals(zone, FixedArray::New(zone, locals_.length(), Heap::Tenure_Old)); |
|
asherkin@263
|
368 |
if (!locals) |
|
asherkin@263
|
369 |
return NULL; |
|
asherkin@263
|
370 |
for (size_t i = 0; i < locals_.length(); i++) |
|
asherkin@263
|
371 |
locals->set(zone, i, locals_[i]->type()); |
|
asherkin@263
|
372 |
|
|
asherkin@263
|
373 |
Local<Code> code(zone); |
|
asherkin@263
|
374 |
|
|
asherkin@263
|
375 |
code = Code::New(zone, |
|
asherkin@263
|
376 |
bytes, |
|
asherkin@263
|
377 |
locals, |
|
asherkin@263
|
378 |
objects, |
|
asherkin@263
|
379 |
strings, |
|
asherkin@263
|
380 |
maxStackDepth(), |
|
asherkin@263
|
381 |
maxLoopDepth_, |
|
asherkin@263
|
382 |
safepoints, |
|
asherkin@263
|
383 |
sourcemap); |
|
asherkin@263
|
384 |
|
|
asherkin@263
|
385 |
return code; |
|
asherkin@263
|
386 |
} |