• 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 "ic-inl.h"
35 
36 namespace v8 {
37 namespace internal {
38 
39 // ----------------------------------------------------------------------------
40 // Support macros for defining builtins in C.
41 // ----------------------------------------------------------------------------
42 //
43 // A builtin function is defined by writing:
44 //
45 //   BUILTIN(name) {
46 //     ...
47 //   }
48 //   BUILTIN_END
49 //
50 // In the body of the builtin function, the variable 'receiver' is visible.
51 // The arguments can be accessed through the Arguments object args.
52 //
53 //   args[0]: Receiver (also available as 'receiver')
54 //   args[1]: First argument
55 //     ...
56 //   args[n]: Last argument
57 //   args.length(): Number of arguments including the receiver.
58 // ----------------------------------------------------------------------------
59 
60 
61 // TODO(428): We should consider passing whether or not the
62 // builtin was invoked as a constructor as part of the
63 // arguments. Maybe we also want to pass the called function?
64 #define BUILTIN(name)                                                   \
65   static Object* Builtin_##name(Arguments args) {      \
66     Handle<Object> receiver = args.at<Object>(0);
67 
68 
69 #define BUILTIN_END                             \
70   return Heap::undefined_value();               \
71 }
72 
73 
CalledAsConstructor()74 static inline bool CalledAsConstructor() {
75 #ifdef DEBUG
76   // Calculate the result using a full stack frame iterator and check
77   // that the state of the stack is as we assume it to be in the
78   // code below.
79   StackFrameIterator it;
80   ASSERT(it.frame()->is_exit());
81   it.Advance();
82   StackFrame* frame = it.frame();
83   bool reference_result = frame->is_construct();
84 #endif
85   Address fp = Top::c_entry_fp(Top::GetCurrentThread());
86   // Because we know fp points to an exit frame we can use the relevant
87   // part of ExitFrame::ComputeCallerState directly.
88   const int kCallerOffset = ExitFrameConstants::kCallerFPOffset;
89   Address caller_fp = Memory::Address_at(fp + kCallerOffset);
90   // This inlines the part of StackFrame::ComputeType that grabs the
91   // type of the current frame.  Note that StackFrame::ComputeType
92   // has been specialized for each architecture so if any one of them
93   // changes this code has to be changed as well.
94   const int kMarkerOffset = StandardFrameConstants::kMarkerOffset;
95   const Smi* kConstructMarker = Smi::FromInt(StackFrame::CONSTRUCT);
96   Object* marker = Memory::Object_at(caller_fp + kMarkerOffset);
97   bool result = (marker == kConstructMarker);
98   ASSERT_EQ(result, reference_result);
99   return result;
100 }
101 
102 // ----------------------------------------------------------------------------
103 
104 
GetCode(JavaScript id,bool * resolved)105 Handle<Code> Builtins::GetCode(JavaScript id, bool* resolved) {
106   Code* code = Builtins::builtin(Builtins::Illegal);
107   *resolved = false;
108 
109   if (Top::context() != NULL) {
110     Object* object = Top::builtins()->javascript_builtin(id);
111     if (object->IsJSFunction()) {
112       Handle<JSFunction> function(JSFunction::cast(object));
113       // Make sure the number of parameters match the formal parameter count.
114       ASSERT(function->shared()->formal_parameter_count() ==
115              Builtins::GetArgumentsCount(id));
116       if (function->is_compiled() || CompileLazy(function, CLEAR_EXCEPTION)) {
117         code = function->code();
118         *resolved = true;
119       }
120     }
121   }
122 
123   return Handle<Code>(code);
124 }
125 
126 
BUILTIN(Illegal)127 BUILTIN(Illegal) {
128   UNREACHABLE();
129 }
130 BUILTIN_END
131 
132 
BUILTIN(EmptyFunction)133 BUILTIN(EmptyFunction) {
134 }
135 BUILTIN_END
136 
137 
BUILTIN(ArrayCode)138 BUILTIN(ArrayCode) {
139   JSArray* array;
140   if (CalledAsConstructor()) {
141     array = JSArray::cast(*receiver);
142   } else {
143     // Allocate the JS Array
144     JSFunction* constructor =
145         Top::context()->global_context()->array_function();
146     Object* obj = Heap::AllocateJSObject(constructor);
147     if (obj->IsFailure()) return obj;
148     array = JSArray::cast(obj);
149   }
150 
151   // 'array' now contains the JSArray we should initialize.
152 
153   // Optimize the case where there is one argument and the argument is a
154   // small smi.
155   if (args.length() == 2) {
156     Object* obj = args[1];
157     if (obj->IsSmi()) {
158       int len = Smi::cast(obj)->value();
159       if (len >= 0 && len < JSObject::kInitialMaxFastElementArray) {
160         Object* obj = Heap::AllocateFixedArrayWithHoles(len);
161         if (obj->IsFailure()) return obj;
162         array->SetContent(FixedArray::cast(obj));
163         return array;
164       }
165     }
166     // Take the argument as the length.
167     obj = array->Initialize(0);
168     if (obj->IsFailure()) return obj;
169     if (args.length() == 2) return array->SetElementsLength(args[1]);
170   }
171 
172   // Optimize the case where there are no parameters passed.
173   if (args.length() == 1) return array->Initialize(4);
174 
175   // Take the arguments as elements.
176   int number_of_elements = args.length() - 1;
177   Smi* len = Smi::FromInt(number_of_elements);
178   Object* obj = Heap::AllocateFixedArrayWithHoles(len->value());
179   if (obj->IsFailure()) return obj;
180   FixedArray* elms = FixedArray::cast(obj);
181   WriteBarrierMode mode = elms->GetWriteBarrierMode();
182   // Fill in the content
183   for (int index = 0; index < number_of_elements; index++) {
184     elms->set(index, args[index+1], mode);
185   }
186 
187   // Set length and elements on the array.
188   array->set_elements(FixedArray::cast(obj));
189   array->set_length(len, SKIP_WRITE_BARRIER);
190 
191   return array;
192 }
193 BUILTIN_END
194 
195 
BUILTIN(ArrayPush)196 BUILTIN(ArrayPush) {
197   JSArray* array = JSArray::cast(*receiver);
198   ASSERT(array->HasFastElements());
199 
200   // Make sure we have space for the elements.
201   int len = Smi::cast(array->length())->value();
202 
203   // Set new length.
204   int new_length = len + args.length() - 1;
205   FixedArray* elms = FixedArray::cast(array->elements());
206 
207   if (new_length <= elms->length()) {
208     // Backing storage has extra space for the provided values.
209     for (int index = 0; index < args.length() - 1; index++) {
210       elms->set(index + len, args[index+1]);
211     }
212   } else {
213     // New backing storage is needed.
214     int capacity = new_length + (new_length >> 1) + 16;
215     Object* obj = Heap::AllocateFixedArrayWithHoles(capacity);
216     if (obj->IsFailure()) return obj;
217     FixedArray* new_elms = FixedArray::cast(obj);
218     WriteBarrierMode mode = new_elms->GetWriteBarrierMode();
219     // Fill out the new array with old elements.
220     for (int i = 0; i < len; i++) new_elms->set(i, elms->get(i), mode);
221     // Add the provided values.
222     for (int index = 0; index < args.length() - 1; index++) {
223       new_elms->set(index + len, args[index+1], mode);
224     }
225     // Set the new backing storage.
226     array->set_elements(new_elms);
227   }
228   // Set the length.
229   array->set_length(Smi::FromInt(new_length), SKIP_WRITE_BARRIER);
230   return array->length();
231 }
232 BUILTIN_END
233 
234 
BUILTIN(ArrayPop)235 BUILTIN(ArrayPop) {
236   JSArray* array = JSArray::cast(*receiver);
237   ASSERT(array->HasFastElements());
238   Object* undefined = Heap::undefined_value();
239 
240   int len = Smi::cast(array->length())->value();
241   if (len == 0) return undefined;
242 
243   // Get top element
244   FixedArray* elms = FixedArray::cast(array->elements());
245   Object* top = elms->get(len - 1);
246 
247   // Set the length.
248   array->set_length(Smi::FromInt(len - 1), SKIP_WRITE_BARRIER);
249 
250   if (!top->IsTheHole()) {
251     // Delete the top element.
252     elms->set_the_hole(len - 1);
253     return top;
254   }
255 
256   // Remember to check the prototype chain.
257   JSFunction* array_function =
258       Top::context()->global_context()->array_function();
259   JSObject* prototype = JSObject::cast(array_function->prototype());
260   top = prototype->GetElement(len - 1);
261 
262   return top;
263 }
264 BUILTIN_END
265 
266 
267 // -----------------------------------------------------------------------------
268 //
269 
270 
271 // Returns the holder JSObject if the function can legally be called
272 // with this receiver.  Returns Heap::null_value() if the call is
273 // illegal.  Any arguments that don't fit the expected type is
274 // overwritten with undefined.  Arguments that do fit the expected
275 // type is overwritten with the object in the prototype chain that
276 // actually has that type.
TypeCheck(int argc,Object ** argv,FunctionTemplateInfo * info)277 static inline Object* TypeCheck(int argc,
278                                 Object** argv,
279                                 FunctionTemplateInfo* info) {
280   Object* recv = argv[0];
281   Object* sig_obj = info->signature();
282   if (sig_obj->IsUndefined()) return recv;
283   SignatureInfo* sig = SignatureInfo::cast(sig_obj);
284   // If necessary, check the receiver
285   Object* recv_type = sig->receiver();
286 
287   Object* holder = recv;
288   if (!recv_type->IsUndefined()) {
289     for (; holder != Heap::null_value(); holder = holder->GetPrototype()) {
290       if (holder->IsInstanceOf(FunctionTemplateInfo::cast(recv_type))) {
291         break;
292       }
293     }
294     if (holder == Heap::null_value()) return holder;
295   }
296   Object* args_obj = sig->args();
297   // If there is no argument signature we're done
298   if (args_obj->IsUndefined()) return holder;
299   FixedArray* args = FixedArray::cast(args_obj);
300   int length = args->length();
301   if (argc <= length) length = argc - 1;
302   for (int i = 0; i < length; i++) {
303     Object* argtype = args->get(i);
304     if (argtype->IsUndefined()) continue;
305     Object** arg = &argv[-1 - i];
306     Object* current = *arg;
307     for (; current != Heap::null_value(); current = current->GetPrototype()) {
308       if (current->IsInstanceOf(FunctionTemplateInfo::cast(argtype))) {
309         *arg = current;
310         break;
311       }
312     }
313     if (current == Heap::null_value()) *arg = Heap::undefined_value();
314   }
315   return holder;
316 }
317 
318 
BUILTIN(HandleApiCall)319 BUILTIN(HandleApiCall) {
320   HandleScope scope;
321   bool is_construct = CalledAsConstructor();
322 
323   // TODO(428): Remove use of static variable, handle API callbacks directly.
324   Handle<JSFunction> function =
325       Handle<JSFunction>(JSFunction::cast(Builtins::builtin_passed_function));
326 
327   if (is_construct) {
328     Handle<FunctionTemplateInfo> desc =
329         Handle<FunctionTemplateInfo>(
330             FunctionTemplateInfo::cast(function->shared()->function_data()));
331     bool pending_exception = false;
332     Factory::ConfigureInstance(desc, Handle<JSObject>::cast(receiver),
333                                &pending_exception);
334     ASSERT(Top::has_pending_exception() == pending_exception);
335     if (pending_exception) return Failure::Exception();
336   }
337 
338   FunctionTemplateInfo* fun_data =
339       FunctionTemplateInfo::cast(function->shared()->function_data());
340   Object* raw_holder = TypeCheck(args.length(), &args[0], fun_data);
341 
342   if (raw_holder->IsNull()) {
343     // This function cannot be called with the given receiver.  Abort!
344     Handle<Object> obj =
345         Factory::NewTypeError("illegal_invocation", HandleVector(&function, 1));
346     return Top::Throw(*obj);
347   }
348 
349   Object* raw_call_data = fun_data->call_code();
350   if (!raw_call_data->IsUndefined()) {
351     CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
352     Object* callback_obj = call_data->callback();
353     v8::InvocationCallback callback =
354         v8::ToCData<v8::InvocationCallback>(callback_obj);
355     Object* data_obj = call_data->data();
356     Object* result;
357 
358     v8::Local<v8::Object> self =
359         v8::Utils::ToLocal(Handle<JSObject>::cast(receiver));
360     Handle<Object> data_handle(data_obj);
361     v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle);
362     ASSERT(raw_holder->IsJSObject());
363     v8::Local<v8::Function> callee = v8::Utils::ToLocal(function);
364     Handle<JSObject> holder_handle(JSObject::cast(raw_holder));
365     v8::Local<v8::Object> holder = v8::Utils::ToLocal(holder_handle);
366     LOG(ApiObjectAccess("call", JSObject::cast(*receiver)));
367     v8::Arguments new_args = v8::ImplementationUtilities::NewArguments(
368         data,
369         holder,
370         callee,
371         is_construct,
372         reinterpret_cast<void**>(&args[0] - 1),
373         args.length() - 1);
374 
375     v8::Handle<v8::Value> value;
376     {
377       // Leaving JavaScript.
378       VMState state(EXTERNAL);
379       value = callback(new_args);
380     }
381     if (value.IsEmpty()) {
382       result = Heap::undefined_value();
383     } else {
384       result = *reinterpret_cast<Object**>(*value);
385     }
386 
387     RETURN_IF_SCHEDULED_EXCEPTION();
388     if (!is_construct || result->IsJSObject()) return result;
389   }
390 
391   return *receiver;
392 }
393 BUILTIN_END
394 
395 
396 // Helper function to handle calls to non-function objects created through the
397 // API. The object can be called as either a constructor (using new) or just as
398 // a function (without new).
HandleApiCallAsFunctionOrConstructor(bool is_construct_call,Arguments args)399 static Object* HandleApiCallAsFunctionOrConstructor(bool is_construct_call,
400                                                     Arguments args) {
401   // Non-functions are never called as constructors. Even if this is an object
402   // called as a constructor the delegate call is not a construct call.
403   ASSERT(!CalledAsConstructor());
404 
405   Handle<Object> receiver = args.at<Object>(0);
406 
407   // Get the object called.
408   JSObject* obj = JSObject::cast(*receiver);
409 
410   // Get the invocation callback from the function descriptor that was
411   // used to create the called object.
412   ASSERT(obj->map()->has_instance_call_handler());
413   JSFunction* constructor = JSFunction::cast(obj->map()->constructor());
414   Object* template_info = constructor->shared()->function_data();
415   Object* handler =
416       FunctionTemplateInfo::cast(template_info)->instance_call_handler();
417   ASSERT(!handler->IsUndefined());
418   CallHandlerInfo* call_data = CallHandlerInfo::cast(handler);
419   Object* callback_obj = call_data->callback();
420   v8::InvocationCallback callback =
421       v8::ToCData<v8::InvocationCallback>(callback_obj);
422 
423   // Get the data for the call and perform the callback.
424   Object* data_obj = call_data->data();
425   Object* result;
426   { HandleScope scope;
427     v8::Local<v8::Object> self =
428         v8::Utils::ToLocal(Handle<JSObject>::cast(receiver));
429     Handle<Object> data_handle(data_obj);
430     v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle);
431     Handle<JSFunction> callee_handle(constructor);
432     v8::Local<v8::Function> callee = v8::Utils::ToLocal(callee_handle);
433     LOG(ApiObjectAccess("call non-function", JSObject::cast(*receiver)));
434     v8::Arguments new_args = v8::ImplementationUtilities::NewArguments(
435         data,
436         self,
437         callee,
438         is_construct_call,
439         reinterpret_cast<void**>(&args[0] - 1),
440         args.length() - 1);
441     v8::Handle<v8::Value> value;
442     {
443       // Leaving JavaScript.
444       VMState state(EXTERNAL);
445       value = callback(new_args);
446     }
447     if (value.IsEmpty()) {
448       result = Heap::undefined_value();
449     } else {
450       result = *reinterpret_cast<Object**>(*value);
451     }
452   }
453   // Check for exceptions and return result.
454   RETURN_IF_SCHEDULED_EXCEPTION();
455   return result;
456 }
457 
458 
459 // Handle calls to non-function objects created through the API. This delegate
460 // function is used when the call is a normal function call.
BUILTIN(HandleApiCallAsFunction)461 BUILTIN(HandleApiCallAsFunction) {
462   return HandleApiCallAsFunctionOrConstructor(false, args);
463 }
464 BUILTIN_END
465 
466 
467 // Handle calls to non-function objects created through the API. This delegate
468 // function is used when the call is a construct call.
BUILTIN(HandleApiCallAsConstructor)469 BUILTIN(HandleApiCallAsConstructor) {
470   return HandleApiCallAsFunctionOrConstructor(true, args);
471 }
472 BUILTIN_END
473 
474 
475 // TODO(1238487): This is a nasty hack. We need to improve the way we
476 // call builtins considerable to get rid of this and the hairy macros
477 // in builtins.cc.
478 Object* Builtins::builtin_passed_function;
479 
480 
481 
Generate_LoadIC_ArrayLength(MacroAssembler * masm)482 static void Generate_LoadIC_ArrayLength(MacroAssembler* masm) {
483   LoadIC::GenerateArrayLength(masm);
484 }
485 
486 
Generate_LoadIC_StringLength(MacroAssembler * masm)487 static void Generate_LoadIC_StringLength(MacroAssembler* masm) {
488   LoadIC::GenerateStringLength(masm);
489 }
490 
491 
Generate_LoadIC_FunctionPrototype(MacroAssembler * masm)492 static void Generate_LoadIC_FunctionPrototype(MacroAssembler* masm) {
493   LoadIC::GenerateFunctionPrototype(masm);
494 }
495 
496 
Generate_LoadIC_Initialize(MacroAssembler * masm)497 static void Generate_LoadIC_Initialize(MacroAssembler* masm) {
498   LoadIC::GenerateInitialize(masm);
499 }
500 
501 
Generate_LoadIC_PreMonomorphic(MacroAssembler * masm)502 static void Generate_LoadIC_PreMonomorphic(MacroAssembler* masm) {
503   LoadIC::GeneratePreMonomorphic(masm);
504 }
505 
506 
Generate_LoadIC_Miss(MacroAssembler * masm)507 static void Generate_LoadIC_Miss(MacroAssembler* masm) {
508   LoadIC::GenerateMiss(masm);
509 }
510 
511 
Generate_LoadIC_Megamorphic(MacroAssembler * masm)512 static void Generate_LoadIC_Megamorphic(MacroAssembler* masm) {
513   LoadIC::GenerateMegamorphic(masm);
514 }
515 
516 
Generate_LoadIC_Normal(MacroAssembler * masm)517 static void Generate_LoadIC_Normal(MacroAssembler* masm) {
518   LoadIC::GenerateNormal(masm);
519 }
520 
521 
Generate_KeyedLoadIC_Initialize(MacroAssembler * masm)522 static void Generate_KeyedLoadIC_Initialize(MacroAssembler* masm) {
523   KeyedLoadIC::GenerateInitialize(masm);
524 }
525 
526 
Generate_KeyedLoadIC_Miss(MacroAssembler * masm)527 static void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
528   KeyedLoadIC::GenerateMiss(masm);
529 }
530 
531 
Generate_KeyedLoadIC_Generic(MacroAssembler * masm)532 static void Generate_KeyedLoadIC_Generic(MacroAssembler* masm) {
533   KeyedLoadIC::GenerateGeneric(masm);
534 }
535 
536 
Generate_KeyedLoadIC_PreMonomorphic(MacroAssembler * masm)537 static void Generate_KeyedLoadIC_PreMonomorphic(MacroAssembler* masm) {
538   KeyedLoadIC::GeneratePreMonomorphic(masm);
539 }
540 
541 
Generate_StoreIC_Initialize(MacroAssembler * masm)542 static void Generate_StoreIC_Initialize(MacroAssembler* masm) {
543   StoreIC::GenerateInitialize(masm);
544 }
545 
546 
Generate_StoreIC_Miss(MacroAssembler * masm)547 static void Generate_StoreIC_Miss(MacroAssembler* masm) {
548   StoreIC::GenerateMiss(masm);
549 }
550 
551 
Generate_StoreIC_ExtendStorage(MacroAssembler * masm)552 static void Generate_StoreIC_ExtendStorage(MacroAssembler* masm) {
553   StoreIC::GenerateExtendStorage(masm);
554 }
555 
Generate_StoreIC_Megamorphic(MacroAssembler * masm)556 static void Generate_StoreIC_Megamorphic(MacroAssembler* masm) {
557   StoreIC::GenerateMegamorphic(masm);
558 }
559 
560 
Generate_KeyedStoreIC_Generic(MacroAssembler * masm)561 static void Generate_KeyedStoreIC_Generic(MacroAssembler* masm) {
562   KeyedStoreIC::GenerateGeneric(masm);
563 }
564 
565 
Generate_KeyedStoreIC_ExtendStorage(MacroAssembler * masm)566 static void Generate_KeyedStoreIC_ExtendStorage(MacroAssembler* masm) {
567   KeyedStoreIC::GenerateExtendStorage(masm);
568 }
569 
570 
Generate_KeyedStoreIC_Miss(MacroAssembler * masm)571 static void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
572   KeyedStoreIC::GenerateMiss(masm);
573 }
574 
575 
Generate_KeyedStoreIC_Initialize(MacroAssembler * masm)576 static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) {
577   KeyedStoreIC::GenerateInitialize(masm);
578 }
579 
580 
581 #ifdef ENABLE_DEBUGGER_SUPPORT
Generate_LoadIC_DebugBreak(MacroAssembler * masm)582 static void Generate_LoadIC_DebugBreak(MacroAssembler* masm) {
583   Debug::GenerateLoadICDebugBreak(masm);
584 }
585 
586 
Generate_StoreIC_DebugBreak(MacroAssembler * masm)587 static void Generate_StoreIC_DebugBreak(MacroAssembler* masm) {
588   Debug::GenerateStoreICDebugBreak(masm);
589 }
590 
591 
Generate_KeyedLoadIC_DebugBreak(MacroAssembler * masm)592 static void Generate_KeyedLoadIC_DebugBreak(MacroAssembler* masm) {
593   Debug::GenerateKeyedLoadICDebugBreak(masm);
594 }
595 
596 
Generate_KeyedStoreIC_DebugBreak(MacroAssembler * masm)597 static void Generate_KeyedStoreIC_DebugBreak(MacroAssembler* masm) {
598   Debug::GenerateKeyedStoreICDebugBreak(masm);
599 }
600 
601 
Generate_ConstructCall_DebugBreak(MacroAssembler * masm)602 static void Generate_ConstructCall_DebugBreak(MacroAssembler* masm) {
603   Debug::GenerateConstructCallDebugBreak(masm);
604 }
605 
606 
Generate_Return_DebugBreak(MacroAssembler * masm)607 static void Generate_Return_DebugBreak(MacroAssembler* masm) {
608   Debug::GenerateReturnDebugBreak(masm);
609 }
610 
611 
Generate_Return_DebugBreakEntry(MacroAssembler * masm)612 static void Generate_Return_DebugBreakEntry(MacroAssembler* masm) {
613   Debug::GenerateReturnDebugBreakEntry(masm);
614 }
615 
616 
Generate_StubNoRegisters_DebugBreak(MacroAssembler * masm)617 static void Generate_StubNoRegisters_DebugBreak(MacroAssembler* masm) {
618   Debug::GenerateStubNoRegistersDebugBreak(masm);
619 }
620 #endif
621 
622 Object* Builtins::builtins_[builtin_count] = { NULL, };
623 const char* Builtins::names_[builtin_count] = { NULL, };
624 
625 #define DEF_ENUM_C(name) FUNCTION_ADDR(Builtin_##name),
626   Address Builtins::c_functions_[cfunction_count] = {
627     BUILTIN_LIST_C(DEF_ENUM_C)
628   };
629 #undef DEF_ENUM_C
630 
631 #define DEF_JS_NAME(name, ignore) #name,
632 #define DEF_JS_ARGC(ignore, argc) argc,
633 const char* Builtins::javascript_names_[id_count] = {
634   BUILTINS_LIST_JS(DEF_JS_NAME)
635 };
636 
637 int Builtins::javascript_argc_[id_count] = {
638   BUILTINS_LIST_JS(DEF_JS_ARGC)
639 };
640 #undef DEF_JS_NAME
641 #undef DEF_JS_ARGC
642 
643 static bool is_initialized = false;
Setup(bool create_heap_objects)644 void Builtins::Setup(bool create_heap_objects) {
645   ASSERT(!is_initialized);
646 
647   // Create a scope for the handles in the builtins.
648   HandleScope scope;
649 
650   struct BuiltinDesc {
651     byte* generator;
652     byte* c_code;
653     const char* s_name;  // name is only used for generating log information.
654     int name;
655     Code::Flags flags;
656   };
657 
658 #define DEF_FUNCTION_PTR_C(name)         \
659     { FUNCTION_ADDR(Generate_Adaptor),   \
660       FUNCTION_ADDR(Builtin_##name),     \
661       #name,                             \
662       c_##name,                          \
663       Code::ComputeFlags(Code::BUILTIN)  \
664     },
665 
666 #define DEF_FUNCTION_PTR_A(name, kind, state)              \
667     { FUNCTION_ADDR(Generate_##name),                      \
668       NULL,                                                \
669       #name,                                               \
670       name,                                                \
671       Code::ComputeFlags(Code::kind, NOT_IN_LOOP, state)   \
672     },
673 
674   // Define array of pointers to generators and C builtin functions.
675   static BuiltinDesc functions[] = {
676       BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
677       BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
678       BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
679       // Terminator:
680       { NULL, NULL, NULL, builtin_count, static_cast<Code::Flags>(0) }
681   };
682 
683 #undef DEF_FUNCTION_PTR_C
684 #undef DEF_FUNCTION_PTR_A
685 
686   // For now we generate builtin adaptor code into a stack-allocated
687   // buffer, before copying it into individual code objects.
688   byte buffer[4*KB];
689 
690   // Traverse the list of builtins and generate an adaptor in a
691   // separate code object for each one.
692   for (int i = 0; i < builtin_count; i++) {
693     if (create_heap_objects) {
694       MacroAssembler masm(buffer, sizeof buffer);
695       // Generate the code/adaptor.
696       typedef void (*Generator)(MacroAssembler*, int);
697       Generator g = FUNCTION_CAST<Generator>(functions[i].generator);
698       // We pass all arguments to the generator, but it may not use all of
699       // them.  This works because the first arguments are on top of the
700       // stack.
701       g(&masm, functions[i].name);
702       // Move the code into the object heap.
703       CodeDesc desc;
704       masm.GetCode(&desc);
705       Code::Flags flags =  functions[i].flags;
706       Object* code;
707       {
708         // During startup it's OK to always allocate and defer GC to later.
709         // This simplifies things because we don't need to retry.
710         AlwaysAllocateScope __scope__;
711         code = Heap::CreateCode(desc, NULL, flags, masm.CodeObject());
712         if (code->IsFailure()) {
713           v8::internal::V8::FatalProcessOutOfMemory("CreateCode");
714         }
715       }
716       // Add any unresolved jumps or calls to the fixup list in the
717       // bootstrapper.
718       Bootstrapper::AddFixup(Code::cast(code), &masm);
719       // Log the event and add the code to the builtins array.
720       LOG(CodeCreateEvent(Logger::BUILTIN_TAG,
721                           Code::cast(code), functions[i].s_name));
722       builtins_[i] = code;
723 #ifdef ENABLE_DISASSEMBLER
724       if (FLAG_print_builtin_code) {
725         PrintF("Builtin: %s\n", functions[i].s_name);
726         Code::cast(code)->Disassemble(functions[i].s_name);
727         PrintF("\n");
728       }
729 #endif
730     } else {
731       // Deserializing. The values will be filled in during IterateBuiltins.
732       builtins_[i] = NULL;
733     }
734     names_[i] = functions[i].s_name;
735   }
736 
737   // Mark as initialized.
738   is_initialized = true;
739 }
740 
741 
TearDown()742 void Builtins::TearDown() {
743   is_initialized = false;
744 }
745 
746 
IterateBuiltins(ObjectVisitor * v)747 void Builtins::IterateBuiltins(ObjectVisitor* v) {
748   v->VisitPointers(&builtins_[0], &builtins_[0] + builtin_count);
749 }
750 
751 
Lookup(byte * pc)752 const char* Builtins::Lookup(byte* pc) {
753   if (is_initialized) {  // may be called during initialization (disassembler!)
754     for (int i = 0; i < builtin_count; i++) {
755       Code* entry = Code::cast(builtins_[i]);
756       if (entry->contains(pc)) {
757         return names_[i];
758       }
759     }
760   }
761   return NULL;
762 }
763 
764 
765 } }  // namespace v8::internal
766