Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(701)

Side by Side Diff: src/builtins.cc

Issue 6685088: Merge isolates to bleeding_edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/builtins.h ('k') | src/checks.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 #endif 100 #endif
101 101
102 102
103 #define DEF_ARG_TYPE(name, spec) \ 103 #define DEF_ARG_TYPE(name, spec) \
104 typedef BuiltinArguments<spec> name##ArgumentsType; 104 typedef BuiltinArguments<spec> name##ArgumentsType;
105 BUILTIN_LIST_C(DEF_ARG_TYPE) 105 BUILTIN_LIST_C(DEF_ARG_TYPE)
106 #undef DEF_ARG_TYPE 106 #undef DEF_ARG_TYPE
107 107
108 } // namespace 108 } // namespace
109 109
110
111 // ---------------------------------------------------------------------------- 110 // ----------------------------------------------------------------------------
112 // Support macro for defining builtins in C++. 111 // Support macro for defining builtins in C++.
113 // ---------------------------------------------------------------------------- 112 // ----------------------------------------------------------------------------
114 // 113 //
115 // A builtin function is defined by writing: 114 // A builtin function is defined by writing:
116 // 115 //
117 // BUILTIN(name) { 116 // BUILTIN(name) {
118 // ... 117 // ...
119 // } 118 // }
120 // 119 //
121 // In the body of the builtin function the arguments can be accessed 120 // In the body of the builtin function the arguments can be accessed
122 // through the BuiltinArguments object args. 121 // through the BuiltinArguments object args.
123 122
124 #ifdef DEBUG 123 #ifdef DEBUG
125 124
126 #define BUILTIN(name) \ 125 #define BUILTIN(name) \
127 MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \ 126 MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \
128 name##ArgumentsType args); \ 127 name##ArgumentsType args, Isolate* isolate); \
129 MUST_USE_RESULT static MaybeObject* Builtin_##name( \ 128 MUST_USE_RESULT static MaybeObject* Builtin_##name( \
130 name##ArgumentsType args) { \ 129 name##ArgumentsType args, Isolate* isolate) { \
131 args.Verify(); \ 130 ASSERT(isolate == Isolate::Current()); \
132 return Builtin_Impl_##name(args); \ 131 args.Verify(); \
133 } \ 132 return Builtin_Impl_##name(args, isolate); \
134 MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \ 133 } \
135 name##ArgumentsType args) 134 MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \
135 name##ArgumentsType args, Isolate* isolate)
136 136
137 #else // For release mode. 137 #else // For release mode.
138 138
139 #define BUILTIN(name) \ 139 #define BUILTIN(name) \
140 static MaybeObject* Builtin_##name(name##ArgumentsType args) 140 static MaybeObject* Builtin_##name(name##ArgumentsType args, Isolate* isolate)
141 141
142 #endif 142 #endif
143 143
144 144
145 static inline bool CalledAsConstructor() { 145 static inline bool CalledAsConstructor(Isolate* isolate) {
146 #ifdef DEBUG 146 #ifdef DEBUG
147 // Calculate the result using a full stack frame iterator and check 147 // Calculate the result using a full stack frame iterator and check
148 // that the state of the stack is as we assume it to be in the 148 // that the state of the stack is as we assume it to be in the
149 // code below. 149 // code below.
150 StackFrameIterator it; 150 StackFrameIterator it;
151 ASSERT(it.frame()->is_exit()); 151 ASSERT(it.frame()->is_exit());
152 it.Advance(); 152 it.Advance();
153 StackFrame* frame = it.frame(); 153 StackFrame* frame = it.frame();
154 bool reference_result = frame->is_construct(); 154 bool reference_result = frame->is_construct();
155 #endif 155 #endif
156 Address fp = Top::c_entry_fp(Top::GetCurrentThread()); 156 Address fp = Isolate::c_entry_fp(isolate->thread_local_top());
157 // Because we know fp points to an exit frame we can use the relevant 157 // Because we know fp points to an exit frame we can use the relevant
158 // part of ExitFrame::ComputeCallerState directly. 158 // part of ExitFrame::ComputeCallerState directly.
159 const int kCallerOffset = ExitFrameConstants::kCallerFPOffset; 159 const int kCallerOffset = ExitFrameConstants::kCallerFPOffset;
160 Address caller_fp = Memory::Address_at(fp + kCallerOffset); 160 Address caller_fp = Memory::Address_at(fp + kCallerOffset);
161 // This inlines the part of StackFrame::ComputeType that grabs the 161 // This inlines the part of StackFrame::ComputeType that grabs the
162 // type of the current frame. Note that StackFrame::ComputeType 162 // type of the current frame. Note that StackFrame::ComputeType
163 // has been specialized for each architecture so if any one of them 163 // has been specialized for each architecture so if any one of them
164 // changes this code has to be changed as well. 164 // changes this code has to be changed as well.
165 const int kMarkerOffset = StandardFrameConstants::kMarkerOffset; 165 const int kMarkerOffset = StandardFrameConstants::kMarkerOffset;
166 const Smi* kConstructMarker = Smi::FromInt(StackFrame::CONSTRUCT); 166 const Smi* kConstructMarker = Smi::FromInt(StackFrame::CONSTRUCT);
167 Object* marker = Memory::Object_at(caller_fp + kMarkerOffset); 167 Object* marker = Memory::Object_at(caller_fp + kMarkerOffset);
168 bool result = (marker == kConstructMarker); 168 bool result = (marker == kConstructMarker);
169 ASSERT_EQ(result, reference_result); 169 ASSERT_EQ(result, reference_result);
170 return result; 170 return result;
171 } 171 }
172 172
173 // ---------------------------------------------------------------------------- 173 // ----------------------------------------------------------------------------
174 174
175
176 BUILTIN(Illegal) { 175 BUILTIN(Illegal) {
177 UNREACHABLE(); 176 UNREACHABLE();
178 return Heap::undefined_value(); // Make compiler happy. 177 return isolate->heap()->undefined_value(); // Make compiler happy.
179 } 178 }
180 179
181 180
182 BUILTIN(EmptyFunction) { 181 BUILTIN(EmptyFunction) {
183 return Heap::undefined_value(); 182 return isolate->heap()->undefined_value();
184 } 183 }
185 184
186 185
187 BUILTIN(ArrayCodeGeneric) { 186 BUILTIN(ArrayCodeGeneric) {
188 Counters::array_function_runtime.Increment(); 187 Heap* heap = isolate->heap();
188 isolate->counters()->array_function_runtime()->Increment();
189 189
190 JSArray* array; 190 JSArray* array;
191 if (CalledAsConstructor()) { 191 if (CalledAsConstructor(isolate)) {
192 array = JSArray::cast(*args.receiver()); 192 array = JSArray::cast(*args.receiver());
193 } else { 193 } else {
194 // Allocate the JS Array 194 // Allocate the JS Array
195 JSFunction* constructor = 195 JSFunction* constructor =
196 Top::context()->global_context()->array_function(); 196 isolate->context()->global_context()->array_function();
197 Object* obj; 197 Object* obj;
198 { MaybeObject* maybe_obj = Heap::AllocateJSObject(constructor); 198 { MaybeObject* maybe_obj = heap->AllocateJSObject(constructor);
199 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 199 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
200 } 200 }
201 array = JSArray::cast(obj); 201 array = JSArray::cast(obj);
202 } 202 }
203 203
204 // 'array' now contains the JSArray we should initialize. 204 // 'array' now contains the JSArray we should initialize.
205 ASSERT(array->HasFastElements()); 205 ASSERT(array->HasFastElements());
206 206
207 // Optimize the case where there is one argument and the argument is a 207 // Optimize the case where there is one argument and the argument is a
208 // small smi. 208 // small smi.
209 if (args.length() == 2) { 209 if (args.length() == 2) {
210 Object* obj = args[1]; 210 Object* obj = args[1];
211 if (obj->IsSmi()) { 211 if (obj->IsSmi()) {
212 int len = Smi::cast(obj)->value(); 212 int len = Smi::cast(obj)->value();
213 if (len >= 0 && len < JSObject::kInitialMaxFastElementArray) { 213 if (len >= 0 && len < JSObject::kInitialMaxFastElementArray) {
214 Object* obj; 214 Object* obj;
215 { MaybeObject* maybe_obj = Heap::AllocateFixedArrayWithHoles(len); 215 { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(len);
216 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 216 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
217 } 217 }
218 array->SetContent(FixedArray::cast(obj)); 218 array->SetContent(FixedArray::cast(obj));
219 return array; 219 return array;
220 } 220 }
221 } 221 }
222 // Take the argument as the length. 222 // Take the argument as the length.
223 { MaybeObject* maybe_obj = array->Initialize(0); 223 { MaybeObject* maybe_obj = array->Initialize(0);
224 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 224 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
225 } 225 }
226 return array->SetElementsLength(args[1]); 226 return array->SetElementsLength(args[1]);
227 } 227 }
228 228
229 // Optimize the case where there are no parameters passed. 229 // Optimize the case where there are no parameters passed.
230 if (args.length() == 1) { 230 if (args.length() == 1) {
231 return array->Initialize(JSArray::kPreallocatedArrayElements); 231 return array->Initialize(JSArray::kPreallocatedArrayElements);
232 } 232 }
233 233
234 // Take the arguments as elements. 234 // Take the arguments as elements.
235 int number_of_elements = args.length() - 1; 235 int number_of_elements = args.length() - 1;
236 Smi* len = Smi::FromInt(number_of_elements); 236 Smi* len = Smi::FromInt(number_of_elements);
237 Object* obj; 237 Object* obj;
238 { MaybeObject* maybe_obj = Heap::AllocateFixedArrayWithHoles(len->value()); 238 { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(len->value());
239 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 239 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
240 } 240 }
241 241
242 AssertNoAllocation no_gc; 242 AssertNoAllocation no_gc;
243 FixedArray* elms = FixedArray::cast(obj); 243 FixedArray* elms = FixedArray::cast(obj);
244 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); 244 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
245 // Fill in the content 245 // Fill in the content
246 for (int index = 0; index < number_of_elements; index++) { 246 for (int index = 0; index < number_of_elements; index++) {
247 elms->set(index, args[index+1], mode); 247 elms->set(index, args[index+1], mode);
248 } 248 }
249 249
250 // Set length and elements on the array. 250 // Set length and elements on the array.
251 array->set_elements(FixedArray::cast(obj)); 251 array->set_elements(FixedArray::cast(obj));
252 array->set_length(len); 252 array->set_length(len);
253 253
254 return array; 254 return array;
255 } 255 }
256 256
257 257
258 MUST_USE_RESULT static MaybeObject* AllocateJSArray() { 258 MUST_USE_RESULT static MaybeObject* AllocateJSArray(Heap* heap) {
259 JSFunction* array_function = 259 JSFunction* array_function =
260 Top::context()->global_context()->array_function(); 260 heap->isolate()->context()->global_context()->array_function();
261 Object* result; 261 Object* result;
262 { MaybeObject* maybe_result = Heap::AllocateJSObject(array_function); 262 { MaybeObject* maybe_result = heap->AllocateJSObject(array_function);
263 if (!maybe_result->ToObject(&result)) return maybe_result; 263 if (!maybe_result->ToObject(&result)) return maybe_result;
264 } 264 }
265 return result; 265 return result;
266 } 266 }
267 267
268 268
269 MUST_USE_RESULT static MaybeObject* AllocateEmptyJSArray() { 269 MUST_USE_RESULT static MaybeObject* AllocateEmptyJSArray(Heap* heap) {
270 Object* result; 270 Object* result;
271 { MaybeObject* maybe_result = AllocateJSArray(); 271 { MaybeObject* maybe_result = AllocateJSArray(heap);
272 if (!maybe_result->ToObject(&result)) return maybe_result; 272 if (!maybe_result->ToObject(&result)) return maybe_result;
273 } 273 }
274 JSArray* result_array = JSArray::cast(result); 274 JSArray* result_array = JSArray::cast(result);
275 result_array->set_length(Smi::FromInt(0)); 275 result_array->set_length(Smi::FromInt(0));
276 result_array->set_elements(Heap::empty_fixed_array()); 276 result_array->set_elements(heap->empty_fixed_array());
277 return result_array; 277 return result_array;
278 } 278 }
279 279
280 280
281 static void CopyElements(AssertNoAllocation* no_gc, 281 static void CopyElements(Heap* heap,
282 AssertNoAllocation* no_gc,
282 FixedArray* dst, 283 FixedArray* dst,
283 int dst_index, 284 int dst_index,
284 FixedArray* src, 285 FixedArray* src,
285 int src_index, 286 int src_index,
286 int len) { 287 int len) {
287 ASSERT(dst != src); // Use MoveElements instead. 288 ASSERT(dst != src); // Use MoveElements instead.
288 ASSERT(dst->map() != Heap::fixed_cow_array_map()); 289 ASSERT(dst->map() != HEAP->fixed_cow_array_map());
289 ASSERT(len > 0); 290 ASSERT(len > 0);
290 CopyWords(dst->data_start() + dst_index, 291 CopyWords(dst->data_start() + dst_index,
291 src->data_start() + src_index, 292 src->data_start() + src_index,
292 len); 293 len);
293 WriteBarrierMode mode = dst->GetWriteBarrierMode(*no_gc); 294 WriteBarrierMode mode = dst->GetWriteBarrierMode(*no_gc);
294 if (mode == UPDATE_WRITE_BARRIER) { 295 if (mode == UPDATE_WRITE_BARRIER) {
295 Heap::RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len); 296 heap->RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len);
296 } 297 }
297 } 298 }
298 299
299 300
300 static void MoveElements(AssertNoAllocation* no_gc, 301 static void MoveElements(Heap* heap,
302 AssertNoAllocation* no_gc,
301 FixedArray* dst, 303 FixedArray* dst,
302 int dst_index, 304 int dst_index,
303 FixedArray* src, 305 FixedArray* src,
304 int src_index, 306 int src_index,
305 int len) { 307 int len) {
306 ASSERT(dst->map() != Heap::fixed_cow_array_map()); 308 ASSERT(dst->map() != HEAP->fixed_cow_array_map());
307 memmove(dst->data_start() + dst_index, 309 memmove(dst->data_start() + dst_index,
308 src->data_start() + src_index, 310 src->data_start() + src_index,
309 len * kPointerSize); 311 len * kPointerSize);
310 WriteBarrierMode mode = dst->GetWriteBarrierMode(*no_gc); 312 WriteBarrierMode mode = dst->GetWriteBarrierMode(*no_gc);
311 if (mode == UPDATE_WRITE_BARRIER) { 313 if (mode == UPDATE_WRITE_BARRIER) {
312 Heap::RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len); 314 heap->RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len);
313 } 315 }
314 } 316 }
315 317
316 318
317 static void FillWithHoles(FixedArray* dst, int from, int to) { 319 static void FillWithHoles(Heap* heap, FixedArray* dst, int from, int to) {
318 ASSERT(dst->map() != Heap::fixed_cow_array_map()); 320 ASSERT(dst->map() != heap->fixed_cow_array_map());
319 MemsetPointer(dst->data_start() + from, Heap::the_hole_value(), to - from); 321 MemsetPointer(dst->data_start() + from, heap->the_hole_value(), to - from);
320 } 322 }
321 323
322 324
323 static FixedArray* LeftTrimFixedArray(FixedArray* elms, int to_trim) { 325 static FixedArray* LeftTrimFixedArray(Heap* heap,
324 ASSERT(elms->map() != Heap::fixed_cow_array_map()); 326 FixedArray* elms,
327 int to_trim) {
328 ASSERT(elms->map() != HEAP->fixed_cow_array_map());
325 // For now this trick is only applied to fixed arrays in new and paged space. 329 // For now this trick is only applied to fixed arrays in new and paged space.
326 // In large object space the object's start must coincide with chunk 330 // In large object space the object's start must coincide with chunk
327 // and thus the trick is just not applicable. 331 // and thus the trick is just not applicable.
328 ASSERT(!Heap::lo_space()->Contains(elms)); 332 ASSERT(!HEAP->lo_space()->Contains(elms));
329 333
330 STATIC_ASSERT(FixedArray::kMapOffset == 0); 334 STATIC_ASSERT(FixedArray::kMapOffset == 0);
331 STATIC_ASSERT(FixedArray::kLengthOffset == kPointerSize); 335 STATIC_ASSERT(FixedArray::kLengthOffset == kPointerSize);
332 STATIC_ASSERT(FixedArray::kHeaderSize == 2 * kPointerSize); 336 STATIC_ASSERT(FixedArray::kHeaderSize == 2 * kPointerSize);
333 337
334 Object** former_start = HeapObject::RawField(elms, 0); 338 Object** former_start = HeapObject::RawField(elms, 0);
335 339
336 const int len = elms->length(); 340 const int len = elms->length();
337 341
338 if (to_trim > FixedArray::kHeaderSize / kPointerSize && 342 if (to_trim > FixedArray::kHeaderSize / kPointerSize &&
339 !Heap::new_space()->Contains(elms)) { 343 !heap->new_space()->Contains(elms)) {
340 // If we are doing a big trim in old space then we zap the space that was 344 // If we are doing a big trim in old space then we zap the space that was
341 // formerly part of the array so that the GC (aided by the card-based 345 // formerly part of the array so that the GC (aided by the card-based
342 // remembered set) won't find pointers to new-space there. 346 // remembered set) won't find pointers to new-space there.
343 Object** zap = reinterpret_cast<Object**>(elms->address()); 347 Object** zap = reinterpret_cast<Object**>(elms->address());
344 zap++; // Header of filler must be at least one word so skip that. 348 zap++; // Header of filler must be at least one word so skip that.
345 for (int i = 1; i < to_trim; i++) { 349 for (int i = 1; i < to_trim; i++) {
346 *zap++ = Smi::FromInt(0); 350 *zap++ = Smi::FromInt(0);
347 } 351 }
348 } 352 }
349 // Technically in new space this write might be omitted (except for 353 // Technically in new space this write might be omitted (except for
350 // debug mode which iterates through the heap), but to play safer 354 // debug mode which iterates through the heap), but to play safer
351 // we still do it. 355 // we still do it.
352 Heap::CreateFillerObjectAt(elms->address(), to_trim * kPointerSize); 356 heap->CreateFillerObjectAt(elms->address(), to_trim * kPointerSize);
353 357
354 former_start[to_trim] = Heap::fixed_array_map(); 358 former_start[to_trim] = heap->fixed_array_map();
355 former_start[to_trim + 1] = Smi::FromInt(len - to_trim); 359 former_start[to_trim + 1] = Smi::FromInt(len - to_trim);
356 360
357 return FixedArray::cast(HeapObject::FromAddress( 361 return FixedArray::cast(HeapObject::FromAddress(
358 elms->address() + to_trim * kPointerSize)); 362 elms->address() + to_trim * kPointerSize));
359 } 363 }
360 364
361 365
362 static bool ArrayPrototypeHasNoElements(Context* global_context, 366 static bool ArrayPrototypeHasNoElements(Heap* heap,
367 Context* global_context,
363 JSObject* array_proto) { 368 JSObject* array_proto) {
364 // This method depends on non writability of Object and Array prototype 369 // This method depends on non writability of Object and Array prototype
365 // fields. 370 // fields.
366 if (array_proto->elements() != Heap::empty_fixed_array()) return false; 371 if (array_proto->elements() != heap->empty_fixed_array()) return false;
367 // Hidden prototype 372 // Hidden prototype
368 array_proto = JSObject::cast(array_proto->GetPrototype()); 373 array_proto = JSObject::cast(array_proto->GetPrototype());
369 ASSERT(array_proto->elements() == Heap::empty_fixed_array()); 374 ASSERT(array_proto->elements() == heap->empty_fixed_array());
370 // Object.prototype 375 // Object.prototype
371 Object* proto = array_proto->GetPrototype(); 376 Object* proto = array_proto->GetPrototype();
372 if (proto == Heap::null_value()) return false; 377 if (proto == heap->null_value()) return false;
373 array_proto = JSObject::cast(proto); 378 array_proto = JSObject::cast(proto);
374 if (array_proto != global_context->initial_object_prototype()) return false; 379 if (array_proto != global_context->initial_object_prototype()) return false;
375 if (array_proto->elements() != Heap::empty_fixed_array()) return false; 380 if (array_proto->elements() != heap->empty_fixed_array()) return false;
376 ASSERT(array_proto->GetPrototype()->IsNull()); 381 ASSERT(array_proto->GetPrototype()->IsNull());
377 return true; 382 return true;
378 } 383 }
379 384
380 385
381 MUST_USE_RESULT 386 MUST_USE_RESULT
382 static inline MaybeObject* EnsureJSArrayWithWritableFastElements( 387 static inline MaybeObject* EnsureJSArrayWithWritableFastElements(
383 Object* receiver) { 388 Heap* heap, Object* receiver) {
384 if (!receiver->IsJSArray()) return NULL; 389 if (!receiver->IsJSArray()) return NULL;
385 JSArray* array = JSArray::cast(receiver); 390 JSArray* array = JSArray::cast(receiver);
386 HeapObject* elms = array->elements(); 391 HeapObject* elms = array->elements();
387 if (elms->map() == Heap::fixed_array_map()) return elms; 392 if (elms->map() == heap->fixed_array_map()) return elms;
388 if (elms->map() == Heap::fixed_cow_array_map()) { 393 if (elms->map() == heap->fixed_cow_array_map()) {
389 return array->EnsureWritableFastElements(); 394 return array->EnsureWritableFastElements();
390 } 395 }
391 return NULL; 396 return NULL;
392 } 397 }
393 398
394 399
395 static inline bool IsJSArrayFastElementMovingAllowed(JSArray* receiver) { 400 static inline bool IsJSArrayFastElementMovingAllowed(Heap* heap,
396 Context* global_context = Top::context()->global_context(); 401 JSArray* receiver) {
402 Context* global_context = heap->isolate()->context()->global_context();
397 JSObject* array_proto = 403 JSObject* array_proto =
398 JSObject::cast(global_context->array_function()->prototype()); 404 JSObject::cast(global_context->array_function()->prototype());
399 return receiver->GetPrototype() == array_proto && 405 return receiver->GetPrototype() == array_proto &&
400 ArrayPrototypeHasNoElements(global_context, array_proto); 406 ArrayPrototypeHasNoElements(heap, global_context, array_proto);
401 } 407 }
402 408
403 409
404 MUST_USE_RESULT static MaybeObject* CallJsBuiltin( 410 MUST_USE_RESULT static MaybeObject* CallJsBuiltin(
411 Isolate* isolate,
405 const char* name, 412 const char* name,
406 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) { 413 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
407 HandleScope handleScope; 414 HandleScope handleScope(isolate);
408 415
409 Handle<Object> js_builtin = 416 Handle<Object> js_builtin =
410 GetProperty(Handle<JSObject>(Top::global_context()->builtins()), 417 GetProperty(Handle<JSObject>(
411 name); 418 isolate->global_context()->builtins()),
419 name);
412 ASSERT(js_builtin->IsJSFunction()); 420 ASSERT(js_builtin->IsJSFunction());
413 Handle<JSFunction> function(Handle<JSFunction>::cast(js_builtin)); 421 Handle<JSFunction> function(Handle<JSFunction>::cast(js_builtin));
414 ScopedVector<Object**> argv(args.length() - 1); 422 ScopedVector<Object**> argv(args.length() - 1);
415 int n_args = args.length() - 1; 423 int n_args = args.length() - 1;
416 for (int i = 0; i < n_args; i++) { 424 for (int i = 0; i < n_args; i++) {
417 argv[i] = args.at<Object>(i + 1).location(); 425 argv[i] = args.at<Object>(i + 1).location();
418 } 426 }
419 bool pending_exception = false; 427 bool pending_exception = false;
420 Handle<Object> result = Execution::Call(function, 428 Handle<Object> result = Execution::Call(function,
421 args.receiver(), 429 args.receiver(),
422 n_args, 430 n_args,
423 argv.start(), 431 argv.start(),
424 &pending_exception); 432 &pending_exception);
425 if (pending_exception) return Failure::Exception(); 433 if (pending_exception) return Failure::Exception();
426 return *result; 434 return *result;
427 } 435 }
428 436
429 437
430 BUILTIN(ArrayPush) { 438 BUILTIN(ArrayPush) {
439 Heap* heap = isolate->heap();
431 Object* receiver = *args.receiver(); 440 Object* receiver = *args.receiver();
432 Object* elms_obj; 441 Object* elms_obj;
433 { MaybeObject* maybe_elms_obj = 442 { MaybeObject* maybe_elms_obj =
434 EnsureJSArrayWithWritableFastElements(receiver); 443 EnsureJSArrayWithWritableFastElements(heap, receiver);
435 if (maybe_elms_obj == NULL) return CallJsBuiltin("ArrayPush", args); 444 if (maybe_elms_obj == NULL) {
445 return CallJsBuiltin(isolate, "ArrayPush", args);
446 }
436 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; 447 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
437 } 448 }
438 FixedArray* elms = FixedArray::cast(elms_obj); 449 FixedArray* elms = FixedArray::cast(elms_obj);
439 JSArray* array = JSArray::cast(receiver); 450 JSArray* array = JSArray::cast(receiver);
440 451
441 int len = Smi::cast(array->length())->value(); 452 int len = Smi::cast(array->length())->value();
442 int to_add = args.length() - 1; 453 int to_add = args.length() - 1;
443 if (to_add == 0) { 454 if (to_add == 0) {
444 return Smi::FromInt(len); 455 return Smi::FromInt(len);
445 } 456 }
446 // Currently fixed arrays cannot grow too big, so 457 // Currently fixed arrays cannot grow too big, so
447 // we should never hit this case. 458 // we should never hit this case.
448 ASSERT(to_add <= (Smi::kMaxValue - len)); 459 ASSERT(to_add <= (Smi::kMaxValue - len));
449 460
450 int new_length = len + to_add; 461 int new_length = len + to_add;
451 462
452 if (new_length > elms->length()) { 463 if (new_length > elms->length()) {
453 // New backing storage is needed. 464 // New backing storage is needed.
454 int capacity = new_length + (new_length >> 1) + 16; 465 int capacity = new_length + (new_length >> 1) + 16;
455 Object* obj; 466 Object* obj;
456 { MaybeObject* maybe_obj = Heap::AllocateUninitializedFixedArray(capacity); 467 { MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity);
457 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 468 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
458 } 469 }
459 FixedArray* new_elms = FixedArray::cast(obj); 470 FixedArray* new_elms = FixedArray::cast(obj);
460 471
461 AssertNoAllocation no_gc; 472 AssertNoAllocation no_gc;
462 if (len > 0) { 473 if (len > 0) {
463 CopyElements(&no_gc, new_elms, 0, elms, 0, len); 474 CopyElements(heap, &no_gc, new_elms, 0, elms, 0, len);
464 } 475 }
465 FillWithHoles(new_elms, new_length, capacity); 476 FillWithHoles(heap, new_elms, new_length, capacity);
466 477
467 elms = new_elms; 478 elms = new_elms;
468 array->set_elements(elms); 479 array->set_elements(elms);
469 } 480 }
470 481
471 // Add the provided values. 482 // Add the provided values.
472 AssertNoAllocation no_gc; 483 AssertNoAllocation no_gc;
473 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); 484 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
474 for (int index = 0; index < to_add; index++) { 485 for (int index = 0; index < to_add; index++) {
475 elms->set(index + len, args[index + 1], mode); 486 elms->set(index + len, args[index + 1], mode);
476 } 487 }
477 488
478 // Set the length. 489 // Set the length.
479 array->set_length(Smi::FromInt(new_length)); 490 array->set_length(Smi::FromInt(new_length));
480 return Smi::FromInt(new_length); 491 return Smi::FromInt(new_length);
481 } 492 }
482 493
483 494
484 BUILTIN(ArrayPop) { 495 BUILTIN(ArrayPop) {
496 Heap* heap = isolate->heap();
485 Object* receiver = *args.receiver(); 497 Object* receiver = *args.receiver();
486 Object* elms_obj; 498 Object* elms_obj;
487 { MaybeObject* maybe_elms_obj = 499 { MaybeObject* maybe_elms_obj =
488 EnsureJSArrayWithWritableFastElements(receiver); 500 EnsureJSArrayWithWritableFastElements(heap, receiver);
489 if (maybe_elms_obj == NULL) return CallJsBuiltin("ArrayPop", args); 501 if (maybe_elms_obj == NULL) return CallJsBuiltin(isolate, "ArrayPop", args);
490 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; 502 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
491 } 503 }
492 FixedArray* elms = FixedArray::cast(elms_obj); 504 FixedArray* elms = FixedArray::cast(elms_obj);
493 JSArray* array = JSArray::cast(receiver); 505 JSArray* array = JSArray::cast(receiver);
494 506
495 int len = Smi::cast(array->length())->value(); 507 int len = Smi::cast(array->length())->value();
496 if (len == 0) return Heap::undefined_value(); 508 if (len == 0) return heap->undefined_value();
497 509
498 // Get top element 510 // Get top element
499 MaybeObject* top = elms->get(len - 1); 511 MaybeObject* top = elms->get(len - 1);
500 512
501 // Set the length. 513 // Set the length.
502 array->set_length(Smi::FromInt(len - 1)); 514 array->set_length(Smi::FromInt(len - 1));
503 515
504 if (!top->IsTheHole()) { 516 if (!top->IsTheHole()) {
505 // Delete the top element. 517 // Delete the top element.
506 elms->set_the_hole(len - 1); 518 elms->set_the_hole(len - 1);
507 return top; 519 return top;
508 } 520 }
509 521
510 top = array->GetPrototype()->GetElement(len - 1); 522 top = array->GetPrototype()->GetElement(len - 1);
511 523
512 return top; 524 return top;
513 } 525 }
514 526
515 527
516 BUILTIN(ArrayShift) { 528 BUILTIN(ArrayShift) {
529 Heap* heap = isolate->heap();
517 Object* receiver = *args.receiver(); 530 Object* receiver = *args.receiver();
518 Object* elms_obj; 531 Object* elms_obj;
519 { MaybeObject* maybe_elms_obj = 532 { MaybeObject* maybe_elms_obj =
520 EnsureJSArrayWithWritableFastElements(receiver); 533 EnsureJSArrayWithWritableFastElements(heap, receiver);
521 if (maybe_elms_obj == NULL) return CallJsBuiltin("ArrayShift", args); 534 if (maybe_elms_obj == NULL)
535 return CallJsBuiltin(isolate, "ArrayShift", args);
522 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; 536 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
523 } 537 }
524 if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) { 538 if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) {
525 return CallJsBuiltin("ArrayShift", args); 539 return CallJsBuiltin(isolate, "ArrayShift", args);
526 } 540 }
527 FixedArray* elms = FixedArray::cast(elms_obj); 541 FixedArray* elms = FixedArray::cast(elms_obj);
528 JSArray* array = JSArray::cast(receiver); 542 JSArray* array = JSArray::cast(receiver);
529 ASSERT(array->HasFastElements()); 543 ASSERT(array->HasFastElements());
530 544
531 int len = Smi::cast(array->length())->value(); 545 int len = Smi::cast(array->length())->value();
532 if (len == 0) return Heap::undefined_value(); 546 if (len == 0) return heap->undefined_value();
533 547
534 // Get first element 548 // Get first element
535 Object* first = elms->get(0); 549 Object* first = elms->get(0);
536 if (first->IsTheHole()) { 550 if (first->IsTheHole()) {
537 first = Heap::undefined_value(); 551 first = heap->undefined_value();
538 } 552 }
539 553
540 if (!Heap::lo_space()->Contains(elms)) { 554 if (!heap->lo_space()->Contains(elms)) {
541 // As elms still in the same space they used to be, 555 // As elms still in the same space they used to be,
542 // there is no need to update region dirty mark. 556 // there is no need to update region dirty mark.
543 array->set_elements(LeftTrimFixedArray(elms, 1), SKIP_WRITE_BARRIER); 557 array->set_elements(LeftTrimFixedArray(heap, elms, 1), SKIP_WRITE_BARRIER);
544 } else { 558 } else {
545 // Shift the elements. 559 // Shift the elements.
546 AssertNoAllocation no_gc; 560 AssertNoAllocation no_gc;
547 MoveElements(&no_gc, elms, 0, elms, 1, len - 1); 561 MoveElements(heap, &no_gc, elms, 0, elms, 1, len - 1);
548 elms->set(len - 1, Heap::the_hole_value()); 562 elms->set(len - 1, heap->the_hole_value());
549 } 563 }
550 564
551 // Set the length. 565 // Set the length.
552 array->set_length(Smi::FromInt(len - 1)); 566 array->set_length(Smi::FromInt(len - 1));
553 567
554 return first; 568 return first;
555 } 569 }
556 570
557 571
558 BUILTIN(ArrayUnshift) { 572 BUILTIN(ArrayUnshift) {
573 Heap* heap = isolate->heap();
559 Object* receiver = *args.receiver(); 574 Object* receiver = *args.receiver();
560 Object* elms_obj; 575 Object* elms_obj;
561 { MaybeObject* maybe_elms_obj = 576 { MaybeObject* maybe_elms_obj =
562 EnsureJSArrayWithWritableFastElements(receiver); 577 EnsureJSArrayWithWritableFastElements(heap, receiver);
563 if (maybe_elms_obj == NULL) return CallJsBuiltin("ArrayUnshift", args); 578 if (maybe_elms_obj == NULL)
579 return CallJsBuiltin(isolate, "ArrayUnshift", args);
564 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; 580 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
565 } 581 }
566 if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) { 582 if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) {
567 return CallJsBuiltin("ArrayUnshift", args); 583 return CallJsBuiltin(isolate, "ArrayUnshift", args);
568 } 584 }
569 FixedArray* elms = FixedArray::cast(elms_obj); 585 FixedArray* elms = FixedArray::cast(elms_obj);
570 JSArray* array = JSArray::cast(receiver); 586 JSArray* array = JSArray::cast(receiver);
571 ASSERT(array->HasFastElements()); 587 ASSERT(array->HasFastElements());
572 588
573 int len = Smi::cast(array->length())->value(); 589 int len = Smi::cast(array->length())->value();
574 int to_add = args.length() - 1; 590 int to_add = args.length() - 1;
575 int new_length = len + to_add; 591 int new_length = len + to_add;
576 // Currently fixed arrays cannot grow too big, so 592 // Currently fixed arrays cannot grow too big, so
577 // we should never hit this case. 593 // we should never hit this case.
578 ASSERT(to_add <= (Smi::kMaxValue - len)); 594 ASSERT(to_add <= (Smi::kMaxValue - len));
579 595
580 if (new_length > elms->length()) { 596 if (new_length > elms->length()) {
581 // New backing storage is needed. 597 // New backing storage is needed.
582 int capacity = new_length + (new_length >> 1) + 16; 598 int capacity = new_length + (new_length >> 1) + 16;
583 Object* obj; 599 Object* obj;
584 { MaybeObject* maybe_obj = Heap::AllocateUninitializedFixedArray(capacity); 600 { MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity);
585 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 601 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
586 } 602 }
587 FixedArray* new_elms = FixedArray::cast(obj); 603 FixedArray* new_elms = FixedArray::cast(obj);
588 604
589 AssertNoAllocation no_gc; 605 AssertNoAllocation no_gc;
590 if (len > 0) { 606 if (len > 0) {
591 CopyElements(&no_gc, new_elms, to_add, elms, 0, len); 607 CopyElements(heap, &no_gc, new_elms, to_add, elms, 0, len);
592 } 608 }
593 FillWithHoles(new_elms, new_length, capacity); 609 FillWithHoles(heap, new_elms, new_length, capacity);
594 610
595 elms = new_elms; 611 elms = new_elms;
596 array->set_elements(elms); 612 array->set_elements(elms);
597 } else { 613 } else {
598 AssertNoAllocation no_gc; 614 AssertNoAllocation no_gc;
599 MoveElements(&no_gc, elms, to_add, elms, 0, len); 615 MoveElements(heap, &no_gc, elms, to_add, elms, 0, len);
600 } 616 }
601 617
602 // Add the provided values. 618 // Add the provided values.
603 AssertNoAllocation no_gc; 619 AssertNoAllocation no_gc;
604 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); 620 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
605 for (int i = 0; i < to_add; i++) { 621 for (int i = 0; i < to_add; i++) {
606 elms->set(i, args[i + 1], mode); 622 elms->set(i, args[i + 1], mode);
607 } 623 }
608 624
609 // Set the length. 625 // Set the length.
610 array->set_length(Smi::FromInt(new_length)); 626 array->set_length(Smi::FromInt(new_length));
611 return Smi::FromInt(new_length); 627 return Smi::FromInt(new_length);
612 } 628 }
613 629
614 630
615 BUILTIN(ArraySlice) { 631 BUILTIN(ArraySlice) {
632 Heap* heap = isolate->heap();
616 Object* receiver = *args.receiver(); 633 Object* receiver = *args.receiver();
617 FixedArray* elms; 634 FixedArray* elms;
618 int len = -1; 635 int len = -1;
619 if (receiver->IsJSArray()) { 636 if (receiver->IsJSArray()) {
620 JSArray* array = JSArray::cast(receiver); 637 JSArray* array = JSArray::cast(receiver);
621 if (!array->HasFastElements() || 638 if (!array->HasFastElements() ||
622 !IsJSArrayFastElementMovingAllowed(array)) { 639 !IsJSArrayFastElementMovingAllowed(heap, array)) {
623 return CallJsBuiltin("ArraySlice", args); 640 return CallJsBuiltin(isolate, "ArraySlice", args);
624 } 641 }
625 642
626 elms = FixedArray::cast(array->elements()); 643 elms = FixedArray::cast(array->elements());
627 len = Smi::cast(array->length())->value(); 644 len = Smi::cast(array->length())->value();
628 } else { 645 } else {
629 // Array.slice(arguments, ...) is quite a common idiom (notably more 646 // Array.slice(arguments, ...) is quite a common idiom (notably more
630 // than 50% of invocations in Web apps). Treat it in C++ as well. 647 // than 50% of invocations in Web apps). Treat it in C++ as well.
631 Map* arguments_map = 648 Map* arguments_map =
632 Top::context()->global_context()->arguments_boilerplate()->map(); 649 isolate->context()->global_context()->arguments_boilerplate()->map();
633 650
634 bool is_arguments_object_with_fast_elements = 651 bool is_arguments_object_with_fast_elements =
635 receiver->IsJSObject() 652 receiver->IsJSObject()
636 && JSObject::cast(receiver)->map() == arguments_map 653 && JSObject::cast(receiver)->map() == arguments_map
637 && JSObject::cast(receiver)->HasFastElements(); 654 && JSObject::cast(receiver)->HasFastElements();
638 if (!is_arguments_object_with_fast_elements) { 655 if (!is_arguments_object_with_fast_elements) {
639 return CallJsBuiltin("ArraySlice", args); 656 return CallJsBuiltin(isolate, "ArraySlice", args);
640 } 657 }
641 elms = FixedArray::cast(JSObject::cast(receiver)->elements()); 658 elms = FixedArray::cast(JSObject::cast(receiver)->elements());
642 Object* len_obj = JSObject::cast(receiver) 659 Object* len_obj = JSObject::cast(receiver)
643 ->InObjectPropertyAt(Heap::kArgumentsLengthIndex); 660 ->InObjectPropertyAt(Heap::kArgumentsLengthIndex);
644 if (!len_obj->IsSmi()) { 661 if (!len_obj->IsSmi()) {
645 return CallJsBuiltin("ArraySlice", args); 662 return CallJsBuiltin(isolate, "ArraySlice", args);
646 } 663 }
647 len = Smi::cast(len_obj)->value(); 664 len = Smi::cast(len_obj)->value();
648 if (len > elms->length()) { 665 if (len > elms->length()) {
649 return CallJsBuiltin("ArraySlice", args); 666 return CallJsBuiltin(isolate, "ArraySlice", args);
650 } 667 }
651 for (int i = 0; i < len; i++) { 668 for (int i = 0; i < len; i++) {
652 if (elms->get(i) == Heap::the_hole_value()) { 669 if (elms->get(i) == heap->the_hole_value()) {
653 return CallJsBuiltin("ArraySlice", args); 670 return CallJsBuiltin(isolate, "ArraySlice", args);
654 } 671 }
655 } 672 }
656 } 673 }
657 ASSERT(len >= 0); 674 ASSERT(len >= 0);
658 int n_arguments = args.length() - 1; 675 int n_arguments = args.length() - 1;
659 676
660 // Note carefully choosen defaults---if argument is missing, 677 // Note carefully choosen defaults---if argument is missing,
661 // it's undefined which gets converted to 0 for relative_start 678 // it's undefined which gets converted to 0 for relative_start
662 // and to len for relative_end. 679 // and to len for relative_end.
663 int relative_start = 0; 680 int relative_start = 0;
664 int relative_end = len; 681 int relative_end = len;
665 if (n_arguments > 0) { 682 if (n_arguments > 0) {
666 Object* arg1 = args[1]; 683 Object* arg1 = args[1];
667 if (arg1->IsSmi()) { 684 if (arg1->IsSmi()) {
668 relative_start = Smi::cast(arg1)->value(); 685 relative_start = Smi::cast(arg1)->value();
669 } else if (!arg1->IsUndefined()) { 686 } else if (!arg1->IsUndefined()) {
670 return CallJsBuiltin("ArraySlice", args); 687 return CallJsBuiltin(isolate, "ArraySlice", args);
671 } 688 }
672 if (n_arguments > 1) { 689 if (n_arguments > 1) {
673 Object* arg2 = args[2]; 690 Object* arg2 = args[2];
674 if (arg2->IsSmi()) { 691 if (arg2->IsSmi()) {
675 relative_end = Smi::cast(arg2)->value(); 692 relative_end = Smi::cast(arg2)->value();
676 } else if (!arg2->IsUndefined()) { 693 } else if (!arg2->IsUndefined()) {
677 return CallJsBuiltin("ArraySlice", args); 694 return CallJsBuiltin(isolate, "ArraySlice", args);
678 } 695 }
679 } 696 }
680 } 697 }
681 698
682 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6. 699 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6.
683 int k = (relative_start < 0) ? Max(len + relative_start, 0) 700 int k = (relative_start < 0) ? Max(len + relative_start, 0)
684 : Min(relative_start, len); 701 : Min(relative_start, len);
685 702
686 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8. 703 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8.
687 int final = (relative_end < 0) ? Max(len + relative_end, 0) 704 int final = (relative_end < 0) ? Max(len + relative_end, 0)
688 : Min(relative_end, len); 705 : Min(relative_end, len);
689 706
690 // Calculate the length of result array. 707 // Calculate the length of result array.
691 int result_len = final - k; 708 int result_len = final - k;
692 if (result_len <= 0) { 709 if (result_len <= 0) {
693 return AllocateEmptyJSArray(); 710 return AllocateEmptyJSArray(heap);
694 } 711 }
695 712
696 Object* result; 713 Object* result;
697 { MaybeObject* maybe_result = AllocateJSArray(); 714 { MaybeObject* maybe_result = AllocateJSArray(heap);
698 if (!maybe_result->ToObject(&result)) return maybe_result; 715 if (!maybe_result->ToObject(&result)) return maybe_result;
699 } 716 }
700 JSArray* result_array = JSArray::cast(result); 717 JSArray* result_array = JSArray::cast(result);
701 718
702 { MaybeObject* maybe_result = 719 { MaybeObject* maybe_result =
703 Heap::AllocateUninitializedFixedArray(result_len); 720 heap->AllocateUninitializedFixedArray(result_len);
704 if (!maybe_result->ToObject(&result)) return maybe_result; 721 if (!maybe_result->ToObject(&result)) return maybe_result;
705 } 722 }
706 FixedArray* result_elms = FixedArray::cast(result); 723 FixedArray* result_elms = FixedArray::cast(result);
707 724
708 AssertNoAllocation no_gc; 725 AssertNoAllocation no_gc;
709 CopyElements(&no_gc, result_elms, 0, elms, k, result_len); 726 CopyElements(heap, &no_gc, result_elms, 0, elms, k, result_len);
710 727
711 // Set elements. 728 // Set elements.
712 result_array->set_elements(result_elms); 729 result_array->set_elements(result_elms);
713 730
714 // Set the length. 731 // Set the length.
715 result_array->set_length(Smi::FromInt(result_len)); 732 result_array->set_length(Smi::FromInt(result_len));
716 return result_array; 733 return result_array;
717 } 734 }
718 735
719 736
720 BUILTIN(ArraySplice) { 737 BUILTIN(ArraySplice) {
738 Heap* heap = isolate->heap();
721 Object* receiver = *args.receiver(); 739 Object* receiver = *args.receiver();
722 Object* elms_obj; 740 Object* elms_obj;
723 { MaybeObject* maybe_elms_obj = 741 { MaybeObject* maybe_elms_obj =
724 EnsureJSArrayWithWritableFastElements(receiver); 742 EnsureJSArrayWithWritableFastElements(heap, receiver);
725 if (maybe_elms_obj == NULL) return CallJsBuiltin("ArraySplice", args); 743 if (maybe_elms_obj == NULL)
744 return CallJsBuiltin(isolate, "ArraySplice", args);
726 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; 745 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
727 } 746 }
728 if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) { 747 if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) {
729 return CallJsBuiltin("ArraySplice", args); 748 return CallJsBuiltin(isolate, "ArraySplice", args);
730 } 749 }
731 FixedArray* elms = FixedArray::cast(elms_obj); 750 FixedArray* elms = FixedArray::cast(elms_obj);
732 JSArray* array = JSArray::cast(receiver); 751 JSArray* array = JSArray::cast(receiver);
733 ASSERT(array->HasFastElements()); 752 ASSERT(array->HasFastElements());
734 753
735 int len = Smi::cast(array->length())->value(); 754 int len = Smi::cast(array->length())->value();
736 755
737 int n_arguments = args.length() - 1; 756 int n_arguments = args.length() - 1;
738 757
739 int relative_start = 0; 758 int relative_start = 0;
740 if (n_arguments > 0) { 759 if (n_arguments > 0) {
741 Object* arg1 = args[1]; 760 Object* arg1 = args[1];
742 if (arg1->IsSmi()) { 761 if (arg1->IsSmi()) {
743 relative_start = Smi::cast(arg1)->value(); 762 relative_start = Smi::cast(arg1)->value();
744 } else if (!arg1->IsUndefined()) { 763 } else if (!arg1->IsUndefined()) {
745 return CallJsBuiltin("ArraySplice", args); 764 return CallJsBuiltin(isolate, "ArraySplice", args);
746 } 765 }
747 } 766 }
748 int actual_start = (relative_start < 0) ? Max(len + relative_start, 0) 767 int actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
749 : Min(relative_start, len); 768 : Min(relative_start, len);
750 769
751 // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is 770 // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
752 // given as a request to delete all the elements from the start. 771 // given as a request to delete all the elements from the start.
753 // And it differs from the case of undefined delete count. 772 // And it differs from the case of undefined delete count.
754 // This does not follow ECMA-262, but we do the same for 773 // This does not follow ECMA-262, but we do the same for
755 // compatibility. 774 // compatibility.
756 int actual_delete_count; 775 int actual_delete_count;
757 if (n_arguments == 1) { 776 if (n_arguments == 1) {
758 ASSERT(len - actual_start >= 0); 777 ASSERT(len - actual_start >= 0);
759 actual_delete_count = len - actual_start; 778 actual_delete_count = len - actual_start;
760 } else { 779 } else {
761 int value = 0; // ToInteger(undefined) == 0 780 int value = 0; // ToInteger(undefined) == 0
762 if (n_arguments > 1) { 781 if (n_arguments > 1) {
763 Object* arg2 = args[2]; 782 Object* arg2 = args[2];
764 if (arg2->IsSmi()) { 783 if (arg2->IsSmi()) {
765 value = Smi::cast(arg2)->value(); 784 value = Smi::cast(arg2)->value();
766 } else { 785 } else {
767 return CallJsBuiltin("ArraySplice", args); 786 return CallJsBuiltin(isolate, "ArraySplice", args);
768 } 787 }
769 } 788 }
770 actual_delete_count = Min(Max(value, 0), len - actual_start); 789 actual_delete_count = Min(Max(value, 0), len - actual_start);
771 } 790 }
772 791
773 JSArray* result_array = NULL; 792 JSArray* result_array = NULL;
774 if (actual_delete_count == 0) { 793 if (actual_delete_count == 0) {
775 Object* result; 794 Object* result;
776 { MaybeObject* maybe_result = AllocateEmptyJSArray(); 795 { MaybeObject* maybe_result = AllocateEmptyJSArray(heap);
777 if (!maybe_result->ToObject(&result)) return maybe_result; 796 if (!maybe_result->ToObject(&result)) return maybe_result;
778 } 797 }
779 result_array = JSArray::cast(result); 798 result_array = JSArray::cast(result);
780 } else { 799 } else {
781 // Allocate result array. 800 // Allocate result array.
782 Object* result; 801 Object* result;
783 { MaybeObject* maybe_result = AllocateJSArray(); 802 { MaybeObject* maybe_result = AllocateJSArray(heap);
784 if (!maybe_result->ToObject(&result)) return maybe_result; 803 if (!maybe_result->ToObject(&result)) return maybe_result;
785 } 804 }
786 result_array = JSArray::cast(result); 805 result_array = JSArray::cast(result);
787 806
788 { MaybeObject* maybe_result = 807 { MaybeObject* maybe_result =
789 Heap::AllocateUninitializedFixedArray(actual_delete_count); 808 heap->AllocateUninitializedFixedArray(actual_delete_count);
790 if (!maybe_result->ToObject(&result)) return maybe_result; 809 if (!maybe_result->ToObject(&result)) return maybe_result;
791 } 810 }
792 FixedArray* result_elms = FixedArray::cast(result); 811 FixedArray* result_elms = FixedArray::cast(result);
793 812
794 AssertNoAllocation no_gc; 813 AssertNoAllocation no_gc;
795 // Fill newly created array. 814 // Fill newly created array.
796 CopyElements(&no_gc, 815 CopyElements(heap,
816 &no_gc,
797 result_elms, 0, 817 result_elms, 0,
798 elms, actual_start, 818 elms, actual_start,
799 actual_delete_count); 819 actual_delete_count);
800 820
801 // Set elements. 821 // Set elements.
802 result_array->set_elements(result_elms); 822 result_array->set_elements(result_elms);
803 823
804 // Set the length. 824 // Set the length.
805 result_array->set_length(Smi::FromInt(actual_delete_count)); 825 result_array->set_length(Smi::FromInt(actual_delete_count));
806 } 826 }
807 827
808 int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0; 828 int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0;
809 829
810 int new_length = len - actual_delete_count + item_count; 830 int new_length = len - actual_delete_count + item_count;
811 831
812 if (item_count < actual_delete_count) { 832 if (item_count < actual_delete_count) {
813 // Shrink the array. 833 // Shrink the array.
814 const bool trim_array = !Heap::lo_space()->Contains(elms) && 834 const bool trim_array = !heap->lo_space()->Contains(elms) &&
815 ((actual_start + item_count) < 835 ((actual_start + item_count) <
816 (len - actual_delete_count - actual_start)); 836 (len - actual_delete_count - actual_start));
817 if (trim_array) { 837 if (trim_array) {
818 const int delta = actual_delete_count - item_count; 838 const int delta = actual_delete_count - item_count;
819 839
820 if (actual_start > 0) { 840 if (actual_start > 0) {
821 Object** start = elms->data_start(); 841 Object** start = elms->data_start();
822 memmove(start + delta, start, actual_start * kPointerSize); 842 memmove(start + delta, start, actual_start * kPointerSize);
823 } 843 }
824 844
825 elms = LeftTrimFixedArray(elms, delta); 845 elms = LeftTrimFixedArray(heap, elms, delta);
826 array->set_elements(elms, SKIP_WRITE_BARRIER); 846 array->set_elements(elms, SKIP_WRITE_BARRIER);
827 } else { 847 } else {
828 AssertNoAllocation no_gc; 848 AssertNoAllocation no_gc;
829 MoveElements(&no_gc, 849 MoveElements(heap, &no_gc,
830 elms, actual_start + item_count, 850 elms, actual_start + item_count,
831 elms, actual_start + actual_delete_count, 851 elms, actual_start + actual_delete_count,
832 (len - actual_delete_count - actual_start)); 852 (len - actual_delete_count - actual_start));
833 FillWithHoles(elms, new_length, len); 853 FillWithHoles(heap, elms, new_length, len);
834 } 854 }
835 } else if (item_count > actual_delete_count) { 855 } else if (item_count > actual_delete_count) {
836 // Currently fixed arrays cannot grow too big, so 856 // Currently fixed arrays cannot grow too big, so
837 // we should never hit this case. 857 // we should never hit this case.
838 ASSERT((item_count - actual_delete_count) <= (Smi::kMaxValue - len)); 858 ASSERT((item_count - actual_delete_count) <= (Smi::kMaxValue - len));
839 859
840 // Check if array need to grow. 860 // Check if array need to grow.
841 if (new_length > elms->length()) { 861 if (new_length > elms->length()) {
842 // New backing storage is needed. 862 // New backing storage is needed.
843 int capacity = new_length + (new_length >> 1) + 16; 863 int capacity = new_length + (new_length >> 1) + 16;
844 Object* obj; 864 Object* obj;
845 { MaybeObject* maybe_obj = 865 { MaybeObject* maybe_obj =
846 Heap::AllocateUninitializedFixedArray(capacity); 866 heap->AllocateUninitializedFixedArray(capacity);
847 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 867 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
848 } 868 }
849 FixedArray* new_elms = FixedArray::cast(obj); 869 FixedArray* new_elms = FixedArray::cast(obj);
850 870
851 AssertNoAllocation no_gc; 871 AssertNoAllocation no_gc;
852 // Copy the part before actual_start as is. 872 // Copy the part before actual_start as is.
853 if (actual_start > 0) { 873 if (actual_start > 0) {
854 CopyElements(&no_gc, new_elms, 0, elms, 0, actual_start); 874 CopyElements(heap, &no_gc, new_elms, 0, elms, 0, actual_start);
855 } 875 }
856 const int to_copy = len - actual_delete_count - actual_start; 876 const int to_copy = len - actual_delete_count - actual_start;
857 if (to_copy > 0) { 877 if (to_copy > 0) {
858 CopyElements(&no_gc, 878 CopyElements(heap, &no_gc,
859 new_elms, actual_start + item_count, 879 new_elms, actual_start + item_count,
860 elms, actual_start + actual_delete_count, 880 elms, actual_start + actual_delete_count,
861 to_copy); 881 to_copy);
862 } 882 }
863 FillWithHoles(new_elms, new_length, capacity); 883 FillWithHoles(heap, new_elms, new_length, capacity);
864 884
865 elms = new_elms; 885 elms = new_elms;
866 array->set_elements(elms); 886 array->set_elements(elms);
867 } else { 887 } else {
868 AssertNoAllocation no_gc; 888 AssertNoAllocation no_gc;
869 MoveElements(&no_gc, 889 MoveElements(heap, &no_gc,
870 elms, actual_start + item_count, 890 elms, actual_start + item_count,
871 elms, actual_start + actual_delete_count, 891 elms, actual_start + actual_delete_count,
872 (len - actual_delete_count - actual_start)); 892 (len - actual_delete_count - actual_start));
873 } 893 }
874 } 894 }
875 895
876 AssertNoAllocation no_gc; 896 AssertNoAllocation no_gc;
877 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); 897 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
878 for (int k = actual_start; k < actual_start + item_count; k++) { 898 for (int k = actual_start; k < actual_start + item_count; k++) {
879 elms->set(k, args[3 + k - actual_start], mode); 899 elms->set(k, args[3 + k - actual_start], mode);
880 } 900 }
881 901
882 // Set the length. 902 // Set the length.
883 array->set_length(Smi::FromInt(new_length)); 903 array->set_length(Smi::FromInt(new_length));
884 904
885 return result_array; 905 return result_array;
886 } 906 }
887 907
888 908
889 BUILTIN(ArrayConcat) { 909 BUILTIN(ArrayConcat) {
890 Context* global_context = Top::context()->global_context(); 910 Heap* heap = isolate->heap();
911 Context* global_context = isolate->context()->global_context();
891 JSObject* array_proto = 912 JSObject* array_proto =
892 JSObject::cast(global_context->array_function()->prototype()); 913 JSObject::cast(global_context->array_function()->prototype());
893 if (!ArrayPrototypeHasNoElements(global_context, array_proto)) { 914 if (!ArrayPrototypeHasNoElements(heap, global_context, array_proto)) {
894 return CallJsBuiltin("ArrayConcat", args); 915 return CallJsBuiltin(isolate, "ArrayConcat", args);
895 } 916 }
896 917
897 // Iterate through all the arguments performing checks 918 // Iterate through all the arguments performing checks
898 // and calculating total length. 919 // and calculating total length.
899 int n_arguments = args.length(); 920 int n_arguments = args.length();
900 int result_len = 0; 921 int result_len = 0;
901 for (int i = 0; i < n_arguments; i++) { 922 for (int i = 0; i < n_arguments; i++) {
902 Object* arg = args[i]; 923 Object* arg = args[i];
903 if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastElements() 924 if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastElements()
904 || JSArray::cast(arg)->GetPrototype() != array_proto) { 925 || JSArray::cast(arg)->GetPrototype() != array_proto) {
905 return CallJsBuiltin("ArrayConcat", args); 926 return CallJsBuiltin(isolate, "ArrayConcat", args);
906 } 927 }
907 928
908 int len = Smi::cast(JSArray::cast(arg)->length())->value(); 929 int len = Smi::cast(JSArray::cast(arg)->length())->value();
909 930
910 // We shouldn't overflow when adding another len. 931 // We shouldn't overflow when adding another len.
911 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); 932 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
912 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); 933 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt);
913 USE(kHalfOfMaxInt); 934 USE(kHalfOfMaxInt);
914 result_len += len; 935 result_len += len;
915 ASSERT(result_len >= 0); 936 ASSERT(result_len >= 0);
916 937
917 if (result_len > FixedArray::kMaxLength) { 938 if (result_len > FixedArray::kMaxLength) {
918 return CallJsBuiltin("ArrayConcat", args); 939 return CallJsBuiltin(isolate, "ArrayConcat", args);
919 } 940 }
920 } 941 }
921 942
922 if (result_len == 0) { 943 if (result_len == 0) {
923 return AllocateEmptyJSArray(); 944 return AllocateEmptyJSArray(heap);
924 } 945 }
925 946
926 // Allocate result. 947 // Allocate result.
927 Object* result; 948 Object* result;
928 { MaybeObject* maybe_result = AllocateJSArray(); 949 { MaybeObject* maybe_result = AllocateJSArray(heap);
929 if (!maybe_result->ToObject(&result)) return maybe_result; 950 if (!maybe_result->ToObject(&result)) return maybe_result;
930 } 951 }
931 JSArray* result_array = JSArray::cast(result); 952 JSArray* result_array = JSArray::cast(result);
932 953
933 { MaybeObject* maybe_result = 954 { MaybeObject* maybe_result =
934 Heap::AllocateUninitializedFixedArray(result_len); 955 heap->AllocateUninitializedFixedArray(result_len);
935 if (!maybe_result->ToObject(&result)) return maybe_result; 956 if (!maybe_result->ToObject(&result)) return maybe_result;
936 } 957 }
937 FixedArray* result_elms = FixedArray::cast(result); 958 FixedArray* result_elms = FixedArray::cast(result);
938 959
939 // Copy data. 960 // Copy data.
940 AssertNoAllocation no_gc; 961 AssertNoAllocation no_gc;
941 int start_pos = 0; 962 int start_pos = 0;
942 for (int i = 0; i < n_arguments; i++) { 963 for (int i = 0; i < n_arguments; i++) {
943 JSArray* array = JSArray::cast(args[i]); 964 JSArray* array = JSArray::cast(args[i]);
944 int len = Smi::cast(array->length())->value(); 965 int len = Smi::cast(array->length())->value();
945 if (len > 0) { 966 if (len > 0) {
946 FixedArray* elms = FixedArray::cast(array->elements()); 967 FixedArray* elms = FixedArray::cast(array->elements());
947 CopyElements(&no_gc, result_elms, start_pos, elms, 0, len); 968 CopyElements(heap, &no_gc, result_elms, start_pos, elms, 0, len);
948 start_pos += len; 969 start_pos += len;
949 } 970 }
950 } 971 }
951 ASSERT(start_pos == result_len); 972 ASSERT(start_pos == result_len);
952 973
953 // Set the length and elements. 974 // Set the length and elements.
954 result_array->set_length(Smi::FromInt(result_len)); 975 result_array->set_length(Smi::FromInt(result_len));
955 result_array->set_elements(result_elms); 976 result_array->set_elements(result_elms);
956 977
957 return result_array; 978 return result_array;
958 } 979 }
959 980
960 981
961 // ----------------------------------------------------------------------------- 982 // -----------------------------------------------------------------------------
962 // Strict mode poison pills 983 // Strict mode poison pills
963 984
964 985
965 BUILTIN(StrictArgumentsCallee) { 986 BUILTIN(StrictArgumentsCallee) {
966 HandleScope scope; 987 HandleScope scope;
967 return Top::Throw(*Factory::NewTypeError("strict_arguments_callee", 988 return isolate->Throw(*isolate->factory()->NewTypeError(
968 HandleVector<Object>(NULL, 0))); 989 "strict_arguments_callee", HandleVector<Object>(NULL, 0)));
969 } 990 }
970 991
971 992
972 BUILTIN(StrictArgumentsCaller) { 993 BUILTIN(StrictArgumentsCaller) {
973 HandleScope scope; 994 HandleScope scope;
974 return Top::Throw(*Factory::NewTypeError("strict_arguments_caller", 995 return isolate->Throw(*isolate->factory()->NewTypeError(
975 HandleVector<Object>(NULL, 0))); 996 "strict_arguments_caller", HandleVector<Object>(NULL, 0)));
976 } 997 }
977 998
978 999
979 BUILTIN(StrictFunctionCaller) { 1000 BUILTIN(StrictFunctionCaller) {
980 HandleScope scope; 1001 HandleScope scope;
981 return Top::Throw(*Factory::NewTypeError("strict_function_caller", 1002 return isolate->Throw(*isolate->factory()->NewTypeError(
982 HandleVector<Object>(NULL, 0))); 1003 "strict_function_caller", HandleVector<Object>(NULL, 0)));
983 } 1004 }
984 1005
985 1006
986 BUILTIN(StrictFunctionArguments) { 1007 BUILTIN(StrictFunctionArguments) {
987 HandleScope scope; 1008 HandleScope scope;
988 return Top::Throw(*Factory::NewTypeError("strict_function_arguments", 1009 return isolate->Throw(*isolate->factory()->NewTypeError(
989 HandleVector<Object>(NULL, 0))); 1010 "strict_function_arguments", HandleVector<Object>(NULL, 0)));
990 } 1011 }
991 1012
992 1013
993 // ----------------------------------------------------------------------------- 1014 // -----------------------------------------------------------------------------
994 // 1015 //
995 1016
996 1017
997 // Returns the holder JSObject if the function can legally be called 1018 // Returns the holder JSObject if the function can legally be called
998 // with this receiver. Returns Heap::null_value() if the call is 1019 // with this receiver. Returns Heap::null_value() if the call is
999 // illegal. Any arguments that don't fit the expected type is 1020 // illegal. Any arguments that don't fit the expected type is
1000 // overwritten with undefined. Arguments that do fit the expected 1021 // overwritten with undefined. Arguments that do fit the expected
1001 // type is overwritten with the object in the prototype chain that 1022 // type is overwritten with the object in the prototype chain that
1002 // actually has that type. 1023 // actually has that type.
1003 static inline Object* TypeCheck(int argc, 1024 static inline Object* TypeCheck(Heap* heap,
1025 int argc,
1004 Object** argv, 1026 Object** argv,
1005 FunctionTemplateInfo* info) { 1027 FunctionTemplateInfo* info) {
1006 Object* recv = argv[0]; 1028 Object* recv = argv[0];
1007 Object* sig_obj = info->signature(); 1029 Object* sig_obj = info->signature();
1008 if (sig_obj->IsUndefined()) return recv; 1030 if (sig_obj->IsUndefined()) return recv;
1009 SignatureInfo* sig = SignatureInfo::cast(sig_obj); 1031 SignatureInfo* sig = SignatureInfo::cast(sig_obj);
1010 // If necessary, check the receiver 1032 // If necessary, check the receiver
1011 Object* recv_type = sig->receiver(); 1033 Object* recv_type = sig->receiver();
1012 1034
1013 Object* holder = recv; 1035 Object* holder = recv;
1014 if (!recv_type->IsUndefined()) { 1036 if (!recv_type->IsUndefined()) {
1015 for (; holder != Heap::null_value(); holder = holder->GetPrototype()) { 1037 for (; holder != heap->null_value(); holder = holder->GetPrototype()) {
1016 if (holder->IsInstanceOf(FunctionTemplateInfo::cast(recv_type))) { 1038 if (holder->IsInstanceOf(FunctionTemplateInfo::cast(recv_type))) {
1017 break; 1039 break;
1018 } 1040 }
1019 } 1041 }
1020 if (holder == Heap::null_value()) return holder; 1042 if (holder == heap->null_value()) return holder;
1021 } 1043 }
1022 Object* args_obj = sig->args(); 1044 Object* args_obj = sig->args();
1023 // If there is no argument signature we're done 1045 // If there is no argument signature we're done
1024 if (args_obj->IsUndefined()) return holder; 1046 if (args_obj->IsUndefined()) return holder;
1025 FixedArray* args = FixedArray::cast(args_obj); 1047 FixedArray* args = FixedArray::cast(args_obj);
1026 int length = args->length(); 1048 int length = args->length();
1027 if (argc <= length) length = argc - 1; 1049 if (argc <= length) length = argc - 1;
1028 for (int i = 0; i < length; i++) { 1050 for (int i = 0; i < length; i++) {
1029 Object* argtype = args->get(i); 1051 Object* argtype = args->get(i);
1030 if (argtype->IsUndefined()) continue; 1052 if (argtype->IsUndefined()) continue;
1031 Object** arg = &argv[-1 - i]; 1053 Object** arg = &argv[-1 - i];
1032 Object* current = *arg; 1054 Object* current = *arg;
1033 for (; current != Heap::null_value(); current = current->GetPrototype()) { 1055 for (; current != heap->null_value(); current = current->GetPrototype()) {
1034 if (current->IsInstanceOf(FunctionTemplateInfo::cast(argtype))) { 1056 if (current->IsInstanceOf(FunctionTemplateInfo::cast(argtype))) {
1035 *arg = current; 1057 *arg = current;
1036 break; 1058 break;
1037 } 1059 }
1038 } 1060 }
1039 if (current == Heap::null_value()) *arg = Heap::undefined_value(); 1061 if (current == heap->null_value()) *arg = heap->undefined_value();
1040 } 1062 }
1041 return holder; 1063 return holder;
1042 } 1064 }
1043 1065
1044 1066
1045 template <bool is_construct> 1067 template <bool is_construct>
1046 MUST_USE_RESULT static MaybeObject* HandleApiCallHelper( 1068 MUST_USE_RESULT static MaybeObject* HandleApiCallHelper(
1047 BuiltinArguments<NEEDS_CALLED_FUNCTION> args) { 1069 BuiltinArguments<NEEDS_CALLED_FUNCTION> args, Isolate* isolate) {
1048 ASSERT(is_construct == CalledAsConstructor()); 1070 ASSERT(is_construct == CalledAsConstructor(isolate));
1071 Heap* heap = isolate->heap();
1049 1072
1050 HandleScope scope; 1073 HandleScope scope(isolate);
1051 Handle<JSFunction> function = args.called_function(); 1074 Handle<JSFunction> function = args.called_function();
1052 ASSERT(function->shared()->IsApiFunction()); 1075 ASSERT(function->shared()->IsApiFunction());
1053 1076
1054 FunctionTemplateInfo* fun_data = function->shared()->get_api_func_data(); 1077 FunctionTemplateInfo* fun_data = function->shared()->get_api_func_data();
1055 if (is_construct) { 1078 if (is_construct) {
1056 Handle<FunctionTemplateInfo> desc(fun_data); 1079 Handle<FunctionTemplateInfo> desc(fun_data, isolate);
1057 bool pending_exception = false; 1080 bool pending_exception = false;
1058 Factory::ConfigureInstance(desc, Handle<JSObject>::cast(args.receiver()), 1081 isolate->factory()->ConfigureInstance(
1059 &pending_exception); 1082 desc, Handle<JSObject>::cast(args.receiver()), &pending_exception);
1060 ASSERT(Top::has_pending_exception() == pending_exception); 1083 ASSERT(isolate->has_pending_exception() == pending_exception);
1061 if (pending_exception) return Failure::Exception(); 1084 if (pending_exception) return Failure::Exception();
1062 fun_data = *desc; 1085 fun_data = *desc;
1063 } 1086 }
1064 1087
1065 Object* raw_holder = TypeCheck(args.length(), &args[0], fun_data); 1088 Object* raw_holder = TypeCheck(heap, args.length(), &args[0], fun_data);
1066 1089
1067 if (raw_holder->IsNull()) { 1090 if (raw_holder->IsNull()) {
1068 // This function cannot be called with the given receiver. Abort! 1091 // This function cannot be called with the given receiver. Abort!
1069 Handle<Object> obj = 1092 Handle<Object> obj =
1070 Factory::NewTypeError("illegal_invocation", HandleVector(&function, 1)); 1093 isolate->factory()->NewTypeError(
1071 return Top::Throw(*obj); 1094 "illegal_invocation", HandleVector(&function, 1));
1095 return isolate->Throw(*obj);
1072 } 1096 }
1073 1097
1074 Object* raw_call_data = fun_data->call_code(); 1098 Object* raw_call_data = fun_data->call_code();
1075 if (!raw_call_data->IsUndefined()) { 1099 if (!raw_call_data->IsUndefined()) {
1076 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data); 1100 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
1077 Object* callback_obj = call_data->callback(); 1101 Object* callback_obj = call_data->callback();
1078 v8::InvocationCallback callback = 1102 v8::InvocationCallback callback =
1079 v8::ToCData<v8::InvocationCallback>(callback_obj); 1103 v8::ToCData<v8::InvocationCallback>(callback_obj);
1080 Object* data_obj = call_data->data(); 1104 Object* data_obj = call_data->data();
1081 Object* result; 1105 Object* result;
1082 1106
1083 LOG(ApiObjectAccess("call", JSObject::cast(*args.receiver()))); 1107 LOG(isolate, ApiObjectAccess("call", JSObject::cast(*args.receiver())));
1084 ASSERT(raw_holder->IsJSObject()); 1108 ASSERT(raw_holder->IsJSObject());
1085 1109
1086 CustomArguments custom; 1110 CustomArguments custom(isolate);
1087 v8::ImplementationUtilities::PrepareArgumentsData(custom.end(), 1111 v8::ImplementationUtilities::PrepareArgumentsData(custom.end(),
1088 data_obj, *function, raw_holder); 1112 data_obj, *function, raw_holder);
1089 1113
1090 v8::Arguments new_args = v8::ImplementationUtilities::NewArguments( 1114 v8::Arguments new_args = v8::ImplementationUtilities::NewArguments(
1091 custom.end(), 1115 custom.end(),
1092 &args[0] - 1, 1116 &args[0] - 1,
1093 args.length() - 1, 1117 args.length() - 1,
1094 is_construct); 1118 is_construct);
1095 1119
1096 v8::Handle<v8::Value> value; 1120 v8::Handle<v8::Value> value;
1097 { 1121 {
1098 // Leaving JavaScript. 1122 // Leaving JavaScript.
1099 VMState state(EXTERNAL); 1123 VMState state(isolate, EXTERNAL);
1100 ExternalCallbackScope call_scope(v8::ToCData<Address>(callback_obj)); 1124 ExternalCallbackScope call_scope(isolate,
1125 v8::ToCData<Address>(callback_obj));
1101 value = callback(new_args); 1126 value = callback(new_args);
1102 } 1127 }
1103 if (value.IsEmpty()) { 1128 if (value.IsEmpty()) {
1104 result = Heap::undefined_value(); 1129 result = heap->undefined_value();
1105 } else { 1130 } else {
1106 result = *reinterpret_cast<Object**>(*value); 1131 result = *reinterpret_cast<Object**>(*value);
1107 } 1132 }
1108 1133
1109 RETURN_IF_SCHEDULED_EXCEPTION(); 1134 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1110 if (!is_construct || result->IsJSObject()) return result; 1135 if (!is_construct || result->IsJSObject()) return result;
1111 } 1136 }
1112 1137
1113 return *args.receiver(); 1138 return *args.receiver();
1114 } 1139 }
1115 1140
1116 1141
1117 BUILTIN(HandleApiCall) { 1142 BUILTIN(HandleApiCall) {
1118 return HandleApiCallHelper<false>(args); 1143 return HandleApiCallHelper<false>(args, isolate);
1119 } 1144 }
1120 1145
1121 1146
1122 BUILTIN(HandleApiCallConstruct) { 1147 BUILTIN(HandleApiCallConstruct) {
1123 return HandleApiCallHelper<true>(args); 1148 return HandleApiCallHelper<true>(args, isolate);
1124 } 1149 }
1125 1150
1126 1151
1127 #ifdef DEBUG 1152 #ifdef DEBUG
1128 1153
1129 static void VerifyTypeCheck(Handle<JSObject> object, 1154 static void VerifyTypeCheck(Handle<JSObject> object,
1130 Handle<JSFunction> function) { 1155 Handle<JSFunction> function) {
1131 ASSERT(function->shared()->IsApiFunction()); 1156 ASSERT(function->shared()->IsApiFunction());
1132 FunctionTemplateInfo* info = function->shared()->get_api_func_data(); 1157 FunctionTemplateInfo* info = function->shared()->get_api_func_data();
1133 if (info->signature()->IsUndefined()) return; 1158 if (info->signature()->IsUndefined()) return;
1134 SignatureInfo* signature = SignatureInfo::cast(info->signature()); 1159 SignatureInfo* signature = SignatureInfo::cast(info->signature());
1135 Object* receiver_type = signature->receiver(); 1160 Object* receiver_type = signature->receiver();
1136 if (receiver_type->IsUndefined()) return; 1161 if (receiver_type->IsUndefined()) return;
1137 FunctionTemplateInfo* type = FunctionTemplateInfo::cast(receiver_type); 1162 FunctionTemplateInfo* type = FunctionTemplateInfo::cast(receiver_type);
1138 ASSERT(object->IsInstanceOf(type)); 1163 ASSERT(object->IsInstanceOf(type));
1139 } 1164 }
1140 1165
1141 #endif 1166 #endif
1142 1167
1143 1168
1144 BUILTIN(FastHandleApiCall) { 1169 BUILTIN(FastHandleApiCall) {
1145 ASSERT(!CalledAsConstructor()); 1170 ASSERT(!CalledAsConstructor(isolate));
1171 Heap* heap = isolate->heap();
1146 const bool is_construct = false; 1172 const bool is_construct = false;
1147 1173
1148 // We expect four more arguments: callback, function, call data, and holder. 1174 // We expect four more arguments: callback, function, call data, and holder.
1149 const int args_length = args.length() - 4; 1175 const int args_length = args.length() - 4;
1150 ASSERT(args_length >= 0); 1176 ASSERT(args_length >= 0);
1151 1177
1152 Object* callback_obj = args[args_length]; 1178 Object* callback_obj = args[args_length];
1153 1179
1154 v8::Arguments new_args = v8::ImplementationUtilities::NewArguments( 1180 v8::Arguments new_args = v8::ImplementationUtilities::NewArguments(
1155 &args[args_length + 1], 1181 &args[args_length + 1],
1156 &args[0] - 1, 1182 &args[0] - 1,
1157 args_length - 1, 1183 args_length - 1,
1158 is_construct); 1184 is_construct);
1159 1185
1160 #ifdef DEBUG 1186 #ifdef DEBUG
1161 VerifyTypeCheck(Utils::OpenHandle(*new_args.Holder()), 1187 VerifyTypeCheck(Utils::OpenHandle(*new_args.Holder()),
1162 Utils::OpenHandle(*new_args.Callee())); 1188 Utils::OpenHandle(*new_args.Callee()));
1163 #endif 1189 #endif
1164 HandleScope scope; 1190 HandleScope scope(isolate);
1165 Object* result; 1191 Object* result;
1166 v8::Handle<v8::Value> value; 1192 v8::Handle<v8::Value> value;
1167 { 1193 {
1168 // Leaving JavaScript. 1194 // Leaving JavaScript.
1169 VMState state(EXTERNAL); 1195 VMState state(isolate, EXTERNAL);
1170 ExternalCallbackScope call_scope(v8::ToCData<Address>(callback_obj)); 1196 ExternalCallbackScope call_scope(isolate,
1197 v8::ToCData<Address>(callback_obj));
1171 v8::InvocationCallback callback = 1198 v8::InvocationCallback callback =
1172 v8::ToCData<v8::InvocationCallback>(callback_obj); 1199 v8::ToCData<v8::InvocationCallback>(callback_obj);
1173 1200
1174 value = callback(new_args); 1201 value = callback(new_args);
1175 } 1202 }
1176 if (value.IsEmpty()) { 1203 if (value.IsEmpty()) {
1177 result = Heap::undefined_value(); 1204 result = heap->undefined_value();
1178 } else { 1205 } else {
1179 result = *reinterpret_cast<Object**>(*value); 1206 result = *reinterpret_cast<Object**>(*value);
1180 } 1207 }
1181 1208
1182 RETURN_IF_SCHEDULED_EXCEPTION(); 1209 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1183 return result; 1210 return result;
1184 } 1211 }
1185 1212
1186 1213
1187 // Helper function to handle calls to non-function objects created through the 1214 // Helper function to handle calls to non-function objects created through the
1188 // API. The object can be called as either a constructor (using new) or just as 1215 // API. The object can be called as either a constructor (using new) or just as
1189 // a function (without new). 1216 // a function (without new).
1190 MUST_USE_RESULT static MaybeObject* HandleApiCallAsFunctionOrConstructor( 1217 MUST_USE_RESULT static MaybeObject* HandleApiCallAsFunctionOrConstructor(
1218 Isolate* isolate,
1191 bool is_construct_call, 1219 bool is_construct_call,
1192 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) { 1220 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
1193 // Non-functions are never called as constructors. Even if this is an object 1221 // Non-functions are never called as constructors. Even if this is an object
1194 // called as a constructor the delegate call is not a construct call. 1222 // called as a constructor the delegate call is not a construct call.
1195 ASSERT(!CalledAsConstructor()); 1223 ASSERT(!CalledAsConstructor(isolate));
1224 Heap* heap = isolate->heap();
1196 1225
1197 Handle<Object> receiver = args.at<Object>(0); 1226 Handle<Object> receiver = args.at<Object>(0);
1198 1227
1199 // Get the object called. 1228 // Get the object called.
1200 JSObject* obj = JSObject::cast(*args.receiver()); 1229 JSObject* obj = JSObject::cast(*args.receiver());
1201 1230
1202 // Get the invocation callback from the function descriptor that was 1231 // Get the invocation callback from the function descriptor that was
1203 // used to create the called object. 1232 // used to create the called object.
1204 ASSERT(obj->map()->has_instance_call_handler()); 1233 ASSERT(obj->map()->has_instance_call_handler());
1205 JSFunction* constructor = JSFunction::cast(obj->map()->constructor()); 1234 JSFunction* constructor = JSFunction::cast(obj->map()->constructor());
1206 ASSERT(constructor->shared()->IsApiFunction()); 1235 ASSERT(constructor->shared()->IsApiFunction());
1207 Object* handler = 1236 Object* handler =
1208 constructor->shared()->get_api_func_data()->instance_call_handler(); 1237 constructor->shared()->get_api_func_data()->instance_call_handler();
1209 ASSERT(!handler->IsUndefined()); 1238 ASSERT(!handler->IsUndefined());
1210 CallHandlerInfo* call_data = CallHandlerInfo::cast(handler); 1239 CallHandlerInfo* call_data = CallHandlerInfo::cast(handler);
1211 Object* callback_obj = call_data->callback(); 1240 Object* callback_obj = call_data->callback();
1212 v8::InvocationCallback callback = 1241 v8::InvocationCallback callback =
1213 v8::ToCData<v8::InvocationCallback>(callback_obj); 1242 v8::ToCData<v8::InvocationCallback>(callback_obj);
1214 1243
1215 // Get the data for the call and perform the callback. 1244 // Get the data for the call and perform the callback.
1216 Object* result; 1245 Object* result;
1217 { 1246 {
1218 HandleScope scope; 1247 HandleScope scope(isolate);
1248 LOG(isolate, ApiObjectAccess("call non-function", obj));
1219 1249
1220 LOG(ApiObjectAccess("call non-function", obj)); 1250 CustomArguments custom(isolate);
1221
1222 CustomArguments custom;
1223 v8::ImplementationUtilities::PrepareArgumentsData(custom.end(), 1251 v8::ImplementationUtilities::PrepareArgumentsData(custom.end(),
1224 call_data->data(), constructor, obj); 1252 call_data->data(), constructor, obj);
1225 v8::Arguments new_args = v8::ImplementationUtilities::NewArguments( 1253 v8::Arguments new_args = v8::ImplementationUtilities::NewArguments(
1226 custom.end(), 1254 custom.end(),
1227 &args[0] - 1, 1255 &args[0] - 1,
1228 args.length() - 1, 1256 args.length() - 1,
1229 is_construct_call); 1257 is_construct_call);
1230 v8::Handle<v8::Value> value; 1258 v8::Handle<v8::Value> value;
1231 { 1259 {
1232 // Leaving JavaScript. 1260 // Leaving JavaScript.
1233 VMState state(EXTERNAL); 1261 VMState state(isolate, EXTERNAL);
1234 ExternalCallbackScope call_scope(v8::ToCData<Address>(callback_obj)); 1262 ExternalCallbackScope call_scope(isolate,
1263 v8::ToCData<Address>(callback_obj));
1235 value = callback(new_args); 1264 value = callback(new_args);
1236 } 1265 }
1237 if (value.IsEmpty()) { 1266 if (value.IsEmpty()) {
1238 result = Heap::undefined_value(); 1267 result = heap->undefined_value();
1239 } else { 1268 } else {
1240 result = *reinterpret_cast<Object**>(*value); 1269 result = *reinterpret_cast<Object**>(*value);
1241 } 1270 }
1242 } 1271 }
1243 // Check for exceptions and return result. 1272 // Check for exceptions and return result.
1244 RETURN_IF_SCHEDULED_EXCEPTION(); 1273 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1245 return result; 1274 return result;
1246 } 1275 }
1247 1276
1248 1277
1249 // Handle calls to non-function objects created through the API. This delegate 1278 // Handle calls to non-function objects created through the API. This delegate
1250 // function is used when the call is a normal function call. 1279 // function is used when the call is a normal function call.
1251 BUILTIN(HandleApiCallAsFunction) { 1280 BUILTIN(HandleApiCallAsFunction) {
1252 return HandleApiCallAsFunctionOrConstructor(false, args); 1281 return HandleApiCallAsFunctionOrConstructor(isolate, false, args);
1253 } 1282 }
1254 1283
1255 1284
1256 // Handle calls to non-function objects created through the API. This delegate 1285 // Handle calls to non-function objects created through the API. This delegate
1257 // function is used when the call is a construct call. 1286 // function is used when the call is a construct call.
1258 BUILTIN(HandleApiCallAsConstructor) { 1287 BUILTIN(HandleApiCallAsConstructor) {
1259 return HandleApiCallAsFunctionOrConstructor(true, args); 1288 return HandleApiCallAsFunctionOrConstructor(isolate, true, args);
1260 } 1289 }
1261 1290
1262 1291
1263 static void Generate_LoadIC_ArrayLength(MacroAssembler* masm) { 1292 static void Generate_LoadIC_ArrayLength(MacroAssembler* masm) {
1264 LoadIC::GenerateArrayLength(masm); 1293 LoadIC::GenerateArrayLength(masm);
1265 } 1294 }
1266 1295
1267 1296
1268 static void Generate_LoadIC_StringLength(MacroAssembler* masm) { 1297 static void Generate_LoadIC_StringLength(MacroAssembler* masm) {
1269 LoadIC::GenerateStringLength(masm, false); 1298 LoadIC::GenerateStringLength(masm, false);
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
1458 static void Generate_PlainReturn_LiveEdit(MacroAssembler* masm) { 1487 static void Generate_PlainReturn_LiveEdit(MacroAssembler* masm) {
1459 Debug::GeneratePlainReturnLiveEdit(masm); 1488 Debug::GeneratePlainReturnLiveEdit(masm);
1460 } 1489 }
1461 1490
1462 1491
1463 static void Generate_FrameDropper_LiveEdit(MacroAssembler* masm) { 1492 static void Generate_FrameDropper_LiveEdit(MacroAssembler* masm) {
1464 Debug::GenerateFrameDropperLiveEdit(masm); 1493 Debug::GenerateFrameDropperLiveEdit(masm);
1465 } 1494 }
1466 #endif 1495 #endif
1467 1496
1468 Object* Builtins::builtins_[builtin_count] = { NULL, }; 1497
1469 const char* Builtins::names_[builtin_count] = { NULL, }; 1498 Builtins::Builtins() : initialized_(false) {
1499 memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count);
1500 memset(names_, 0, sizeof(names_[0]) * builtin_count);
1501 }
1502
1503
1504 Builtins::~Builtins() {
1505 }
1506
1470 1507
1471 #define DEF_ENUM_C(name, ignore) FUNCTION_ADDR(Builtin_##name), 1508 #define DEF_ENUM_C(name, ignore) FUNCTION_ADDR(Builtin_##name),
1472 Address Builtins::c_functions_[cfunction_count] = { 1509 Address const Builtins::c_functions_[cfunction_count] = {
1473 BUILTIN_LIST_C(DEF_ENUM_C) 1510 BUILTIN_LIST_C(DEF_ENUM_C)
1474 }; 1511 };
1475 #undef DEF_ENUM_C 1512 #undef DEF_ENUM_C
1476 1513
1477 #define DEF_JS_NAME(name, ignore) #name, 1514 #define DEF_JS_NAME(name, ignore) #name,
1478 #define DEF_JS_ARGC(ignore, argc) argc, 1515 #define DEF_JS_ARGC(ignore, argc) argc,
1479 const char* Builtins::javascript_names_[id_count] = { 1516 const char* const Builtins::javascript_names_[id_count] = {
1480 BUILTINS_LIST_JS(DEF_JS_NAME) 1517 BUILTINS_LIST_JS(DEF_JS_NAME)
1481 }; 1518 };
1482 1519
1483 int Builtins::javascript_argc_[id_count] = { 1520 int const Builtins::javascript_argc_[id_count] = {
1484 BUILTINS_LIST_JS(DEF_JS_ARGC) 1521 BUILTINS_LIST_JS(DEF_JS_ARGC)
1485 }; 1522 };
1486 #undef DEF_JS_NAME 1523 #undef DEF_JS_NAME
1487 #undef DEF_JS_ARGC 1524 #undef DEF_JS_ARGC
1488 1525
1489 static bool is_initialized = false; 1526 struct BuiltinDesc {
1527 byte* generator;
1528 byte* c_code;
1529 const char* s_name; // name is only used for generating log information.
1530 int name;
1531 Code::Flags flags;
1532 BuiltinExtraArguments extra_args;
1533 };
1534
1535 class BuiltinFunctionTable {
1536 public:
1537 BuiltinFunctionTable() {
1538 Builtins::InitBuiltinFunctionTable();
1539 }
1540
1541 static const BuiltinDesc* functions() { return functions_; }
1542
1543 private:
1544 static BuiltinDesc functions_[Builtins::builtin_count + 1];
1545
1546 friend class Builtins;
1547 };
1548
1549 BuiltinDesc BuiltinFunctionTable::functions_[Builtins::builtin_count + 1];
1550
1551 static const BuiltinFunctionTable builtin_function_table_init;
1552
1553 // Define array of pointers to generators and C builtin functions.
1554 // We do this in a sort of roundabout way so that we can do the initialization
1555 // within the lexical scope of Builtins:: and within a context where
1556 // Code::Flags names a non-abstract type.
1557 void Builtins::InitBuiltinFunctionTable() {
1558 BuiltinDesc* functions = BuiltinFunctionTable::functions_;
1559 functions[builtin_count].generator = NULL;
1560 functions[builtin_count].c_code = NULL;
1561 functions[builtin_count].s_name = NULL;
1562 functions[builtin_count].name = builtin_count;
1563 functions[builtin_count].flags = static_cast<Code::Flags>(0);
1564 functions[builtin_count].extra_args = NO_EXTRA_ARGUMENTS;
1565
1566 #define DEF_FUNCTION_PTR_C(aname, aextra_args) \
1567 functions->generator = FUNCTION_ADDR(Generate_Adaptor); \
1568 functions->c_code = FUNCTION_ADDR(Builtin_##aname); \
1569 functions->s_name = #aname; \
1570 functions->name = c_##aname; \
1571 functions->flags = Code::ComputeFlags(Code::BUILTIN); \
1572 functions->extra_args = aextra_args; \
1573 ++functions;
1574
1575 #define DEF_FUNCTION_PTR_A(aname, kind, state, extra) \
1576 functions->generator = FUNCTION_ADDR(Generate_##aname); \
1577 functions->c_code = NULL; \
1578 functions->s_name = #aname; \
1579 functions->name = aname; \
1580 functions->flags = Code::ComputeFlags(Code::kind, \
1581 NOT_IN_LOOP, \
1582 state, \
1583 extra); \
1584 functions->extra_args = NO_EXTRA_ARGUMENTS; \
1585 ++functions;
1586
1587 BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
1588 BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
1589 BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
1590
1591 #undef DEF_FUNCTION_PTR_C
1592 #undef DEF_FUNCTION_PTR_A
1593 }
1594
1490 void Builtins::Setup(bool create_heap_objects) { 1595 void Builtins::Setup(bool create_heap_objects) {
1491 ASSERT(!is_initialized); 1596 ASSERT(!initialized_);
1597 Heap* heap = Isolate::Current()->heap();
1492 1598
1493 // Create a scope for the handles in the builtins. 1599 // Create a scope for the handles in the builtins.
1494 HandleScope scope; 1600 HandleScope scope;
1495 1601
1496 struct BuiltinDesc { 1602 const BuiltinDesc* functions = BuiltinFunctionTable::functions();
1497 byte* generator;
1498 byte* c_code;
1499 const char* s_name; // name is only used for generating log information.
1500 int name;
1501 Code::Flags flags;
1502 BuiltinExtraArguments extra_args;
1503 };
1504
1505 #define DEF_FUNCTION_PTR_C(name, extra_args) \
1506 { FUNCTION_ADDR(Generate_Adaptor), \
1507 FUNCTION_ADDR(Builtin_##name), \
1508 #name, \
1509 c_##name, \
1510 Code::ComputeFlags(Code::BUILTIN), \
1511 extra_args \
1512 },
1513
1514 #define DEF_FUNCTION_PTR_A(name, kind, state, extra) \
1515 { FUNCTION_ADDR(Generate_##name), \
1516 NULL, \
1517 #name, \
1518 name, \
1519 Code::ComputeFlags(Code::kind, NOT_IN_LOOP, state, extra), \
1520 NO_EXTRA_ARGUMENTS \
1521 },
1522
1523 // Define array of pointers to generators and C builtin functions.
1524 static BuiltinDesc functions[] = {
1525 BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
1526 BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
1527 BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
1528 // Terminator:
1529 { NULL, NULL, NULL, builtin_count, static_cast<Code::Flags>(0),
1530 NO_EXTRA_ARGUMENTS }
1531 };
1532
1533 #undef DEF_FUNCTION_PTR_C
1534 #undef DEF_FUNCTION_PTR_A
1535 1603
1536 // For now we generate builtin adaptor code into a stack-allocated 1604 // For now we generate builtin adaptor code into a stack-allocated
1537 // buffer, before copying it into individual code objects. 1605 // buffer, before copying it into individual code objects.
1538 byte buffer[4*KB]; 1606 byte buffer[4*KB];
1539 1607
1540 // Traverse the list of builtins and generate an adaptor in a 1608 // Traverse the list of builtins and generate an adaptor in a
1541 // separate code object for each one. 1609 // separate code object for each one.
1542 for (int i = 0; i < builtin_count; i++) { 1610 for (int i = 0; i < builtin_count; i++) {
1543 if (create_heap_objects) { 1611 if (create_heap_objects) {
1544 MacroAssembler masm(buffer, sizeof buffer); 1612 MacroAssembler masm(buffer, sizeof buffer);
1545 // Generate the code/adaptor. 1613 // Generate the code/adaptor.
1546 typedef void (*Generator)(MacroAssembler*, int, BuiltinExtraArguments); 1614 typedef void (*Generator)(MacroAssembler*, int, BuiltinExtraArguments);
1547 Generator g = FUNCTION_CAST<Generator>(functions[i].generator); 1615 Generator g = FUNCTION_CAST<Generator>(functions[i].generator);
1548 // We pass all arguments to the generator, but it may not use all of 1616 // We pass all arguments to the generator, but it may not use all of
1549 // them. This works because the first arguments are on top of the 1617 // them. This works because the first arguments are on top of the
1550 // stack. 1618 // stack.
1551 g(&masm, functions[i].name, functions[i].extra_args); 1619 g(&masm, functions[i].name, functions[i].extra_args);
1552 // Move the code into the object heap. 1620 // Move the code into the object heap.
1553 CodeDesc desc; 1621 CodeDesc desc;
1554 masm.GetCode(&desc); 1622 masm.GetCode(&desc);
1555 Code::Flags flags = functions[i].flags; 1623 Code::Flags flags = functions[i].flags;
1556 Object* code = NULL; 1624 Object* code = NULL;
1557 { 1625 {
1558 // During startup it's OK to always allocate and defer GC to later. 1626 // During startup it's OK to always allocate and defer GC to later.
1559 // This simplifies things because we don't need to retry. 1627 // This simplifies things because we don't need to retry.
1560 AlwaysAllocateScope __scope__; 1628 AlwaysAllocateScope __scope__;
1561 { MaybeObject* maybe_code = 1629 { MaybeObject* maybe_code =
1562 Heap::CreateCode(desc, flags, masm.CodeObject()); 1630 heap->CreateCode(desc, flags, masm.CodeObject());
1563 if (!maybe_code->ToObject(&code)) { 1631 if (!maybe_code->ToObject(&code)) {
1564 v8::internal::V8::FatalProcessOutOfMemory("CreateCode"); 1632 v8::internal::V8::FatalProcessOutOfMemory("CreateCode");
1565 } 1633 }
1566 } 1634 }
1567 } 1635 }
1568 // Log the event and add the code to the builtins array. 1636 // Log the event and add the code to the builtins array.
1569 PROFILE(CodeCreateEvent(Logger::BUILTIN_TAG, 1637 PROFILE(ISOLATE,
1638 CodeCreateEvent(Logger::BUILTIN_TAG,
1570 Code::cast(code), 1639 Code::cast(code),
1571 functions[i].s_name)); 1640 functions[i].s_name));
1572 GDBJIT(AddCode(GDBJITInterface::BUILTIN, 1641 GDBJIT(AddCode(GDBJITInterface::BUILTIN,
1573 functions[i].s_name, 1642 functions[i].s_name,
1574 Code::cast(code))); 1643 Code::cast(code)));
1575 builtins_[i] = code; 1644 builtins_[i] = code;
1576 #ifdef ENABLE_DISASSEMBLER 1645 #ifdef ENABLE_DISASSEMBLER
1577 if (FLAG_print_builtin_code) { 1646 if (FLAG_print_builtin_code) {
1578 PrintF("Builtin: %s\n", functions[i].s_name); 1647 PrintF("Builtin: %s\n", functions[i].s_name);
1579 Code::cast(code)->Disassemble(functions[i].s_name); 1648 Code::cast(code)->Disassemble(functions[i].s_name);
1580 PrintF("\n"); 1649 PrintF("\n");
1581 } 1650 }
1582 #endif 1651 #endif
1583 } else { 1652 } else {
1584 // Deserializing. The values will be filled in during IterateBuiltins. 1653 // Deserializing. The values will be filled in during IterateBuiltins.
1585 builtins_[i] = NULL; 1654 builtins_[i] = NULL;
1586 } 1655 }
1587 names_[i] = functions[i].s_name; 1656 names_[i] = functions[i].s_name;
1588 } 1657 }
1589 1658
1590 // Mark as initialized. 1659 // Mark as initialized.
1591 is_initialized = true; 1660 initialized_ = true;
1592 } 1661 }
1593 1662
1594 1663
1595 void Builtins::TearDown() { 1664 void Builtins::TearDown() {
1596 is_initialized = false; 1665 initialized_ = false;
1597 } 1666 }
1598 1667
1599 1668
1600 void Builtins::IterateBuiltins(ObjectVisitor* v) { 1669 void Builtins::IterateBuiltins(ObjectVisitor* v) {
1601 v->VisitPointers(&builtins_[0], &builtins_[0] + builtin_count); 1670 v->VisitPointers(&builtins_[0], &builtins_[0] + builtin_count);
1602 } 1671 }
1603 1672
1604 1673
1605 const char* Builtins::Lookup(byte* pc) { 1674 const char* Builtins::Lookup(byte* pc) {
1606 if (is_initialized) { // may be called during initialization (disassembler!) 1675 // may be called during initialization (disassembler!)
1676 if (initialized_) {
1607 for (int i = 0; i < builtin_count; i++) { 1677 for (int i = 0; i < builtin_count; i++) {
1608 Code* entry = Code::cast(builtins_[i]); 1678 Code* entry = Code::cast(builtins_[i]);
1609 if (entry->contains(pc)) { 1679 if (entry->contains(pc)) {
1610 return names_[i]; 1680 return names_[i];
1611 } 1681 }
1612 } 1682 }
1613 } 1683 }
1614 return NULL; 1684 return NULL;
1615 } 1685 }
1616 1686
1617 1687
1618 } } // namespace v8::internal 1688 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/builtins.h ('k') | src/checks.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698