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