blob: b66635c500cfbc450d504ded81bacfe6e72fa812 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// 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
36namespace v8 {
37namespace 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
74static 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
105Handle<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
127BUILTIN(Illegal) {
128 UNREACHABLE();
129}
130BUILTIN_END
131
132
133BUILTIN(EmptyFunction) {
134}
135BUILTIN_END
136
137
138BUILTIN(ArrayCodeGeneric) {
139 Counters::array_function_runtime.Increment();
140
141 JSArray* array;
142 if (CalledAsConstructor()) {
143 array = JSArray::cast(*receiver);
144 } else {
145 // Allocate the JS Array
146 JSFunction* constructor =
147 Top::context()->global_context()->array_function();
148 Object* obj = Heap::AllocateJSObject(constructor);
149 if (obj->IsFailure()) return obj;
150 array = JSArray::cast(obj);
151 }
152
153 // 'array' now contains the JSArray we should initialize.
154
155 // Optimize the case where there is one argument and the argument is a
156 // small smi.
157 if (args.length() == 2) {
158 Object* obj = args[1];
159 if (obj->IsSmi()) {
160 int len = Smi::cast(obj)->value();
161 if (len >= 0 && len < JSObject::kInitialMaxFastElementArray) {
162 Object* obj = Heap::AllocateFixedArrayWithHoles(len);
163 if (obj->IsFailure()) return obj;
164 array->SetContent(FixedArray::cast(obj));
165 return array;
166 }
167 }
168 // Take the argument as the length.
169 obj = array->Initialize(0);
170 if (obj->IsFailure()) return obj;
171 return array->SetElementsLength(args[1]);
172 }
173
174 // Optimize the case where there are no parameters passed.
175 if (args.length() == 1) {
176 return array->Initialize(JSArray::kPreallocatedArrayElements);
177 }
178
179 // Take the arguments as elements.
180 int number_of_elements = args.length() - 1;
181 Smi* len = Smi::FromInt(number_of_elements);
182 Object* obj = Heap::AllocateFixedArrayWithHoles(len->value());
183 if (obj->IsFailure()) return obj;
184 FixedArray* elms = FixedArray::cast(obj);
185 WriteBarrierMode mode = elms->GetWriteBarrierMode();
186 // Fill in the content
187 for (int index = 0; index < number_of_elements; index++) {
188 elms->set(index, args[index+1], mode);
189 }
190
191 // Set length and elements on the array.
192 array->set_elements(FixedArray::cast(obj));
193 array->set_length(len, SKIP_WRITE_BARRIER);
194
195 return array;
196}
197BUILTIN_END
198
199
200BUILTIN(ArrayPush) {
201 JSArray* array = JSArray::cast(*receiver);
202 ASSERT(array->HasFastElements());
203
204 // Make sure we have space for the elements.
205 int len = Smi::cast(array->length())->value();
206
207 // Set new length.
208 int new_length = len + args.length() - 1;
209 FixedArray* elms = FixedArray::cast(array->elements());
210
211 if (new_length <= elms->length()) {
212 // Backing storage has extra space for the provided values.
213 for (int index = 0; index < args.length() - 1; index++) {
214 elms->set(index + len, args[index+1]);
215 }
216 } else {
217 // New backing storage is needed.
218 int capacity = new_length + (new_length >> 1) + 16;
219 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity);
220 if (obj->IsFailure()) return obj;
221 FixedArray* new_elms = FixedArray::cast(obj);
222 WriteBarrierMode mode = new_elms->GetWriteBarrierMode();
223 // Fill out the new array with old elements.
224 for (int i = 0; i < len; i++) new_elms->set(i, elms->get(i), mode);
225 // Add the provided values.
226 for (int index = 0; index < args.length() - 1; index++) {
227 new_elms->set(index + len, args[index+1], mode);
228 }
229 // Set the new backing storage.
230 array->set_elements(new_elms);
231 }
232 // Set the length.
233 array->set_length(Smi::FromInt(new_length), SKIP_WRITE_BARRIER);
234 return array->length();
235}
236BUILTIN_END
237
238
239BUILTIN(ArrayPop) {
240 JSArray* array = JSArray::cast(*receiver);
241 ASSERT(array->HasFastElements());
242 Object* undefined = Heap::undefined_value();
243
244 int len = Smi::cast(array->length())->value();
245 if (len == 0) return undefined;
246
247 // Get top element
248 FixedArray* elms = FixedArray::cast(array->elements());
249 Object* top = elms->get(len - 1);
250
251 // Set the length.
252 array->set_length(Smi::FromInt(len - 1), SKIP_WRITE_BARRIER);
253
254 if (!top->IsTheHole()) {
255 // Delete the top element.
256 elms->set_the_hole(len - 1);
257 return top;
258 }
259
260 // Remember to check the prototype chain.
261 JSFunction* array_function =
262 Top::context()->global_context()->array_function();
263 JSObject* prototype = JSObject::cast(array_function->prototype());
264 top = prototype->GetElement(len - 1);
265
266 return top;
267}
268BUILTIN_END
269
270
271// -----------------------------------------------------------------------------
272//
273
274
275// Returns the holder JSObject if the function can legally be called
276// with this receiver. Returns Heap::null_value() if the call is
277// illegal. Any arguments that don't fit the expected type is
278// overwritten with undefined. Arguments that do fit the expected
279// type is overwritten with the object in the prototype chain that
280// actually has that type.
281static inline Object* TypeCheck(int argc,
282 Object** argv,
283 FunctionTemplateInfo* info) {
284 Object* recv = argv[0];
285 Object* sig_obj = info->signature();
286 if (sig_obj->IsUndefined()) return recv;
287 SignatureInfo* sig = SignatureInfo::cast(sig_obj);
288 // If necessary, check the receiver
289 Object* recv_type = sig->receiver();
290
291 Object* holder = recv;
292 if (!recv_type->IsUndefined()) {
293 for (; holder != Heap::null_value(); holder = holder->GetPrototype()) {
294 if (holder->IsInstanceOf(FunctionTemplateInfo::cast(recv_type))) {
295 break;
296 }
297 }
298 if (holder == Heap::null_value()) return holder;
299 }
300 Object* args_obj = sig->args();
301 // If there is no argument signature we're done
302 if (args_obj->IsUndefined()) return holder;
303 FixedArray* args = FixedArray::cast(args_obj);
304 int length = args->length();
305 if (argc <= length) length = argc - 1;
306 for (int i = 0; i < length; i++) {
307 Object* argtype = args->get(i);
308 if (argtype->IsUndefined()) continue;
309 Object** arg = &argv[-1 - i];
310 Object* current = *arg;
311 for (; current != Heap::null_value(); current = current->GetPrototype()) {
312 if (current->IsInstanceOf(FunctionTemplateInfo::cast(argtype))) {
313 *arg = current;
314 break;
315 }
316 }
317 if (current == Heap::null_value()) *arg = Heap::undefined_value();
318 }
319 return holder;
320}
321
322
323BUILTIN(HandleApiCall) {
324 HandleScope scope;
325 bool is_construct = CalledAsConstructor();
326
327 // TODO(428): Remove use of static variable, handle API callbacks directly.
328 Handle<JSFunction> function =
329 Handle<JSFunction>(JSFunction::cast(Builtins::builtin_passed_function));
330
331 if (is_construct) {
332 Handle<FunctionTemplateInfo> desc =
333 Handle<FunctionTemplateInfo>(
334 FunctionTemplateInfo::cast(function->shared()->function_data()));
335 bool pending_exception = false;
336 Factory::ConfigureInstance(desc, Handle<JSObject>::cast(receiver),
337 &pending_exception);
338 ASSERT(Top::has_pending_exception() == pending_exception);
339 if (pending_exception) return Failure::Exception();
340 }
341
342 FunctionTemplateInfo* fun_data =
343 FunctionTemplateInfo::cast(function->shared()->function_data());
344 Object* raw_holder = TypeCheck(args.length(), &args[0], fun_data);
345
346 if (raw_holder->IsNull()) {
347 // This function cannot be called with the given receiver. Abort!
348 Handle<Object> obj =
349 Factory::NewTypeError("illegal_invocation", HandleVector(&function, 1));
350 return Top::Throw(*obj);
351 }
352
353 Object* raw_call_data = fun_data->call_code();
354 if (!raw_call_data->IsUndefined()) {
355 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
356 Object* callback_obj = call_data->callback();
357 v8::InvocationCallback callback =
358 v8::ToCData<v8::InvocationCallback>(callback_obj);
359 Object* data_obj = call_data->data();
360 Object* result;
361
362 v8::Local<v8::Object> self =
363 v8::Utils::ToLocal(Handle<JSObject>::cast(receiver));
364 Handle<Object> data_handle(data_obj);
365 v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle);
366 ASSERT(raw_holder->IsJSObject());
367 v8::Local<v8::Function> callee = v8::Utils::ToLocal(function);
368 Handle<JSObject> holder_handle(JSObject::cast(raw_holder));
369 v8::Local<v8::Object> holder = v8::Utils::ToLocal(holder_handle);
370 LOG(ApiObjectAccess("call", JSObject::cast(*receiver)));
371 v8::Arguments new_args = v8::ImplementationUtilities::NewArguments(
372 data,
373 holder,
374 callee,
375 is_construct,
376 reinterpret_cast<void**>(&args[0] - 1),
377 args.length() - 1);
378
379 v8::Handle<v8::Value> value;
380 {
381 // Leaving JavaScript.
382 VMState state(EXTERNAL);
Steve Blockd0582a62009-12-15 09:54:21 +0000383#ifdef ENABLE_LOGGING_AND_PROFILING
384 state.set_external_callback(v8::ToCData<Address>(callback_obj));
385#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000386 value = callback(new_args);
387 }
388 if (value.IsEmpty()) {
389 result = Heap::undefined_value();
390 } else {
391 result = *reinterpret_cast<Object**>(*value);
392 }
393
394 RETURN_IF_SCHEDULED_EXCEPTION();
395 if (!is_construct || result->IsJSObject()) return result;
396 }
397
398 return *receiver;
399}
400BUILTIN_END
401
402
403// Helper function to handle calls to non-function objects created through the
404// API. The object can be called as either a constructor (using new) or just as
405// a function (without new).
406static Object* HandleApiCallAsFunctionOrConstructor(bool is_construct_call,
407 Arguments args) {
408 // Non-functions are never called as constructors. Even if this is an object
409 // called as a constructor the delegate call is not a construct call.
410 ASSERT(!CalledAsConstructor());
411
412 Handle<Object> receiver = args.at<Object>(0);
413
414 // Get the object called.
415 JSObject* obj = JSObject::cast(*receiver);
416
417 // Get the invocation callback from the function descriptor that was
418 // used to create the called object.
419 ASSERT(obj->map()->has_instance_call_handler());
420 JSFunction* constructor = JSFunction::cast(obj->map()->constructor());
421 Object* template_info = constructor->shared()->function_data();
422 Object* handler =
423 FunctionTemplateInfo::cast(template_info)->instance_call_handler();
424 ASSERT(!handler->IsUndefined());
425 CallHandlerInfo* call_data = CallHandlerInfo::cast(handler);
426 Object* callback_obj = call_data->callback();
427 v8::InvocationCallback callback =
428 v8::ToCData<v8::InvocationCallback>(callback_obj);
429
430 // Get the data for the call and perform the callback.
431 Object* data_obj = call_data->data();
432 Object* result;
433 { HandleScope scope;
434 v8::Local<v8::Object> self =
435 v8::Utils::ToLocal(Handle<JSObject>::cast(receiver));
436 Handle<Object> data_handle(data_obj);
437 v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle);
438 Handle<JSFunction> callee_handle(constructor);
439 v8::Local<v8::Function> callee = v8::Utils::ToLocal(callee_handle);
440 LOG(ApiObjectAccess("call non-function", JSObject::cast(*receiver)));
441 v8::Arguments new_args = v8::ImplementationUtilities::NewArguments(
442 data,
443 self,
444 callee,
445 is_construct_call,
446 reinterpret_cast<void**>(&args[0] - 1),
447 args.length() - 1);
448 v8::Handle<v8::Value> value;
449 {
450 // Leaving JavaScript.
451 VMState state(EXTERNAL);
Steve Blockd0582a62009-12-15 09:54:21 +0000452#ifdef ENABLE_LOGGING_AND_PROFILING
453 state.set_external_callback(v8::ToCData<Address>(callback_obj));
454#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000455 value = callback(new_args);
456 }
457 if (value.IsEmpty()) {
458 result = Heap::undefined_value();
459 } else {
460 result = *reinterpret_cast<Object**>(*value);
461 }
462 }
463 // Check for exceptions and return result.
464 RETURN_IF_SCHEDULED_EXCEPTION();
465 return result;
466}
467
468
469// Handle calls to non-function objects created through the API. This delegate
470// function is used when the call is a normal function call.
471BUILTIN(HandleApiCallAsFunction) {
472 return HandleApiCallAsFunctionOrConstructor(false, args);
473}
474BUILTIN_END
475
476
477// Handle calls to non-function objects created through the API. This delegate
478// function is used when the call is a construct call.
479BUILTIN(HandleApiCallAsConstructor) {
480 return HandleApiCallAsFunctionOrConstructor(true, args);
481}
482BUILTIN_END
483
484
485// TODO(1238487): This is a nasty hack. We need to improve the way we
486// call builtins considerable to get rid of this and the hairy macros
487// in builtins.cc.
488Object* Builtins::builtin_passed_function;
489
490
491
492static void Generate_LoadIC_ArrayLength(MacroAssembler* masm) {
493 LoadIC::GenerateArrayLength(masm);
494}
495
496
497static void Generate_LoadIC_StringLength(MacroAssembler* masm) {
498 LoadIC::GenerateStringLength(masm);
499}
500
501
502static void Generate_LoadIC_FunctionPrototype(MacroAssembler* masm) {
503 LoadIC::GenerateFunctionPrototype(masm);
504}
505
506
507static void Generate_LoadIC_Initialize(MacroAssembler* masm) {
508 LoadIC::GenerateInitialize(masm);
509}
510
511
512static void Generate_LoadIC_PreMonomorphic(MacroAssembler* masm) {
513 LoadIC::GeneratePreMonomorphic(masm);
514}
515
516
517static void Generate_LoadIC_Miss(MacroAssembler* masm) {
518 LoadIC::GenerateMiss(masm);
519}
520
521
522static void Generate_LoadIC_Megamorphic(MacroAssembler* masm) {
523 LoadIC::GenerateMegamorphic(masm);
524}
525
526
527static void Generate_LoadIC_Normal(MacroAssembler* masm) {
528 LoadIC::GenerateNormal(masm);
529}
530
531
532static void Generate_KeyedLoadIC_Initialize(MacroAssembler* masm) {
533 KeyedLoadIC::GenerateInitialize(masm);
534}
535
536
537static void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
538 KeyedLoadIC::GenerateMiss(masm);
539}
540
541
542static void Generate_KeyedLoadIC_Generic(MacroAssembler* masm) {
543 KeyedLoadIC::GenerateGeneric(masm);
544}
545
546
Steve Block3ce2e202009-11-05 08:53:23 +0000547static void Generate_KeyedLoadIC_ExternalByteArray(MacroAssembler* masm) {
548 KeyedLoadIC::GenerateExternalArray(masm, kExternalByteArray);
549}
550
551
552static void Generate_KeyedLoadIC_ExternalUnsignedByteArray(
553 MacroAssembler* masm) {
554 KeyedLoadIC::GenerateExternalArray(masm, kExternalUnsignedByteArray);
555}
556
557
558static void Generate_KeyedLoadIC_ExternalShortArray(MacroAssembler* masm) {
559 KeyedLoadIC::GenerateExternalArray(masm, kExternalShortArray);
560}
561
562
563static void Generate_KeyedLoadIC_ExternalUnsignedShortArray(
564 MacroAssembler* masm) {
565 KeyedLoadIC::GenerateExternalArray(masm, kExternalUnsignedShortArray);
566}
567
568
569static void Generate_KeyedLoadIC_ExternalIntArray(MacroAssembler* masm) {
570 KeyedLoadIC::GenerateExternalArray(masm, kExternalIntArray);
571}
572
573
574static void Generate_KeyedLoadIC_ExternalUnsignedIntArray(
575 MacroAssembler* masm) {
576 KeyedLoadIC::GenerateExternalArray(masm, kExternalUnsignedIntArray);
577}
578
579
580static void Generate_KeyedLoadIC_ExternalFloatArray(MacroAssembler* masm) {
581 KeyedLoadIC::GenerateExternalArray(masm, kExternalFloatArray);
582}
583
584
Steve Blocka7e24c12009-10-30 11:49:00 +0000585static void Generate_KeyedLoadIC_PreMonomorphic(MacroAssembler* masm) {
586 KeyedLoadIC::GeneratePreMonomorphic(masm);
587}
588
589
590static void Generate_StoreIC_Initialize(MacroAssembler* masm) {
591 StoreIC::GenerateInitialize(masm);
592}
593
594
595static void Generate_StoreIC_Miss(MacroAssembler* masm) {
596 StoreIC::GenerateMiss(masm);
597}
598
599
600static void Generate_StoreIC_ExtendStorage(MacroAssembler* masm) {
601 StoreIC::GenerateExtendStorage(masm);
602}
603
604static void Generate_StoreIC_Megamorphic(MacroAssembler* masm) {
605 StoreIC::GenerateMegamorphic(masm);
606}
607
608
609static void Generate_KeyedStoreIC_Generic(MacroAssembler* masm) {
610 KeyedStoreIC::GenerateGeneric(masm);
611}
612
613
Steve Block3ce2e202009-11-05 08:53:23 +0000614static void Generate_KeyedStoreIC_ExternalByteArray(MacroAssembler* masm) {
615 KeyedStoreIC::GenerateExternalArray(masm, kExternalByteArray);
616}
617
618
619static void Generate_KeyedStoreIC_ExternalUnsignedByteArray(
620 MacroAssembler* masm) {
621 KeyedStoreIC::GenerateExternalArray(masm, kExternalUnsignedByteArray);
622}
623
624
625static void Generate_KeyedStoreIC_ExternalShortArray(MacroAssembler* masm) {
626 KeyedStoreIC::GenerateExternalArray(masm, kExternalShortArray);
627}
628
629
630static void Generate_KeyedStoreIC_ExternalUnsignedShortArray(
631 MacroAssembler* masm) {
632 KeyedStoreIC::GenerateExternalArray(masm, kExternalUnsignedShortArray);
633}
634
635
636static void Generate_KeyedStoreIC_ExternalIntArray(MacroAssembler* masm) {
637 KeyedStoreIC::GenerateExternalArray(masm, kExternalIntArray);
638}
639
640
641static void Generate_KeyedStoreIC_ExternalUnsignedIntArray(
642 MacroAssembler* masm) {
643 KeyedStoreIC::GenerateExternalArray(masm, kExternalUnsignedIntArray);
644}
645
646
647static void Generate_KeyedStoreIC_ExternalFloatArray(MacroAssembler* masm) {
648 KeyedStoreIC::GenerateExternalArray(masm, kExternalFloatArray);
649}
650
651
Steve Blocka7e24c12009-10-30 11:49:00 +0000652static void Generate_KeyedStoreIC_ExtendStorage(MacroAssembler* masm) {
653 KeyedStoreIC::GenerateExtendStorage(masm);
654}
655
656
657static void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
658 KeyedStoreIC::GenerateMiss(masm);
659}
660
661
662static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) {
663 KeyedStoreIC::GenerateInitialize(masm);
664}
665
666
667#ifdef ENABLE_DEBUGGER_SUPPORT
668static void Generate_LoadIC_DebugBreak(MacroAssembler* masm) {
669 Debug::GenerateLoadICDebugBreak(masm);
670}
671
672
673static void Generate_StoreIC_DebugBreak(MacroAssembler* masm) {
674 Debug::GenerateStoreICDebugBreak(masm);
675}
676
677
678static void Generate_KeyedLoadIC_DebugBreak(MacroAssembler* masm) {
679 Debug::GenerateKeyedLoadICDebugBreak(masm);
680}
681
682
683static void Generate_KeyedStoreIC_DebugBreak(MacroAssembler* masm) {
684 Debug::GenerateKeyedStoreICDebugBreak(masm);
685}
686
687
688static void Generate_ConstructCall_DebugBreak(MacroAssembler* masm) {
689 Debug::GenerateConstructCallDebugBreak(masm);
690}
691
692
693static void Generate_Return_DebugBreak(MacroAssembler* masm) {
694 Debug::GenerateReturnDebugBreak(masm);
695}
696
697
698static void Generate_StubNoRegisters_DebugBreak(MacroAssembler* masm) {
699 Debug::GenerateStubNoRegistersDebugBreak(masm);
700}
701#endif
702
703Object* Builtins::builtins_[builtin_count] = { NULL, };
704const char* Builtins::names_[builtin_count] = { NULL, };
705
706#define DEF_ENUM_C(name) FUNCTION_ADDR(Builtin_##name),
707 Address Builtins::c_functions_[cfunction_count] = {
708 BUILTIN_LIST_C(DEF_ENUM_C)
709 };
710#undef DEF_ENUM_C
711
712#define DEF_JS_NAME(name, ignore) #name,
713#define DEF_JS_ARGC(ignore, argc) argc,
714const char* Builtins::javascript_names_[id_count] = {
715 BUILTINS_LIST_JS(DEF_JS_NAME)
716};
717
718int Builtins::javascript_argc_[id_count] = {
719 BUILTINS_LIST_JS(DEF_JS_ARGC)
720};
721#undef DEF_JS_NAME
722#undef DEF_JS_ARGC
723
724static bool is_initialized = false;
725void Builtins::Setup(bool create_heap_objects) {
726 ASSERT(!is_initialized);
727
728 // Create a scope for the handles in the builtins.
729 HandleScope scope;
730
731 struct BuiltinDesc {
732 byte* generator;
733 byte* c_code;
734 const char* s_name; // name is only used for generating log information.
735 int name;
736 Code::Flags flags;
737 };
738
739#define DEF_FUNCTION_PTR_C(name) \
740 { FUNCTION_ADDR(Generate_Adaptor), \
741 FUNCTION_ADDR(Builtin_##name), \
742 #name, \
743 c_##name, \
744 Code::ComputeFlags(Code::BUILTIN) \
745 },
746
747#define DEF_FUNCTION_PTR_A(name, kind, state) \
748 { FUNCTION_ADDR(Generate_##name), \
749 NULL, \
750 #name, \
751 name, \
752 Code::ComputeFlags(Code::kind, NOT_IN_LOOP, state) \
753 },
754
755 // Define array of pointers to generators and C builtin functions.
756 static BuiltinDesc functions[] = {
757 BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
758 BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
759 BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
760 // Terminator:
761 { NULL, NULL, NULL, builtin_count, static_cast<Code::Flags>(0) }
762 };
763
764#undef DEF_FUNCTION_PTR_C
765#undef DEF_FUNCTION_PTR_A
766
767 // For now we generate builtin adaptor code into a stack-allocated
768 // buffer, before copying it into individual code objects.
769 byte buffer[4*KB];
770
771 // Traverse the list of builtins and generate an adaptor in a
772 // separate code object for each one.
773 for (int i = 0; i < builtin_count; i++) {
774 if (create_heap_objects) {
775 MacroAssembler masm(buffer, sizeof buffer);
776 // Generate the code/adaptor.
777 typedef void (*Generator)(MacroAssembler*, int);
778 Generator g = FUNCTION_CAST<Generator>(functions[i].generator);
779 // We pass all arguments to the generator, but it may not use all of
780 // them. This works because the first arguments are on top of the
781 // stack.
782 g(&masm, functions[i].name);
783 // Move the code into the object heap.
784 CodeDesc desc;
785 masm.GetCode(&desc);
786 Code::Flags flags = functions[i].flags;
787 Object* code;
788 {
789 // During startup it's OK to always allocate and defer GC to later.
790 // This simplifies things because we don't need to retry.
791 AlwaysAllocateScope __scope__;
792 code = Heap::CreateCode(desc, NULL, flags, masm.CodeObject());
793 if (code->IsFailure()) {
794 v8::internal::V8::FatalProcessOutOfMemory("CreateCode");
795 }
796 }
797 // Add any unresolved jumps or calls to the fixup list in the
798 // bootstrapper.
799 Bootstrapper::AddFixup(Code::cast(code), &masm);
800 // Log the event and add the code to the builtins array.
801 LOG(CodeCreateEvent(Logger::BUILTIN_TAG,
802 Code::cast(code), functions[i].s_name));
803 builtins_[i] = code;
804#ifdef ENABLE_DISASSEMBLER
805 if (FLAG_print_builtin_code) {
806 PrintF("Builtin: %s\n", functions[i].s_name);
807 Code::cast(code)->Disassemble(functions[i].s_name);
808 PrintF("\n");
809 }
810#endif
811 } else {
812 // Deserializing. The values will be filled in during IterateBuiltins.
813 builtins_[i] = NULL;
814 }
815 names_[i] = functions[i].s_name;
816 }
817
818 // Mark as initialized.
819 is_initialized = true;
820}
821
822
823void Builtins::TearDown() {
824 is_initialized = false;
825}
826
827
828void Builtins::IterateBuiltins(ObjectVisitor* v) {
829 v->VisitPointers(&builtins_[0], &builtins_[0] + builtin_count);
830}
831
832
833const char* Builtins::Lookup(byte* pc) {
834 if (is_initialized) { // may be called during initialization (disassembler!)
835 for (int i = 0; i < builtin_count; i++) {
836 Code* entry = Code::cast(builtins_[i]);
837 if (entry->contains(pc)) {
838 return names_[i];
839 }
840 }
841 }
842 return NULL;
843}
844
845
846} } // namespace v8::internal