blob: db0770f3a96fead16b44b65ec7f5742c865a7e1e [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
Leon Clarkee46be812010-01-19 14:06:41 +000039namespace {
40
41// Arguments object passed to C++ builtins.
42template <BuiltinExtraArguments extra_args>
43class BuiltinArguments : public Arguments {
44 public:
45 BuiltinArguments(int length, Object** arguments)
46 : Arguments(length, arguments) { }
47
48 Object*& operator[] (int index) {
49 ASSERT(index < length());
50 return Arguments::operator[](index);
51 }
52
53 template <class S> Handle<S> at(int index) {
54 ASSERT(index < length());
55 return Arguments::at<S>(index);
56 }
57
58 Handle<Object> receiver() {
59 return Arguments::at<Object>(0);
60 }
61
62 Handle<JSFunction> called_function() {
63 STATIC_ASSERT(extra_args == NEEDS_CALLED_FUNCTION);
64 return Arguments::at<JSFunction>(Arguments::length() - 1);
65 }
66
67 // Gets the total number of arguments including the receiver (but
68 // excluding extra arguments).
69 int length() const {
70 STATIC_ASSERT(extra_args == NO_EXTRA_ARGUMENTS);
71 return Arguments::length();
72 }
73
74#ifdef DEBUG
75 void Verify() {
76 // Check we have at least the receiver.
77 ASSERT(Arguments::length() >= 1);
78 }
79#endif
80};
81
82
83// Specialize BuiltinArguments for the called function extra argument.
84
85template <>
86int BuiltinArguments<NEEDS_CALLED_FUNCTION>::length() const {
87 return Arguments::length() - 1;
88}
89
90#ifdef DEBUG
91template <>
92void BuiltinArguments<NEEDS_CALLED_FUNCTION>::Verify() {
93 // Check we have at least the receiver and the called function.
94 ASSERT(Arguments::length() >= 2);
95 // Make sure cast to JSFunction succeeds.
96 called_function();
97}
98#endif
99
100
101#define DEF_ARG_TYPE(name, spec) \
102 typedef BuiltinArguments<spec> name##ArgumentsType;
103BUILTIN_LIST_C(DEF_ARG_TYPE)
104#undef DEF_ARG_TYPE
105
106} // namespace
107
108
Steve Blocka7e24c12009-10-30 11:49:00 +0000109// ----------------------------------------------------------------------------
Leon Clarkee46be812010-01-19 14:06:41 +0000110// Support macro for defining builtins in C++.
Steve Blocka7e24c12009-10-30 11:49:00 +0000111// ----------------------------------------------------------------------------
112//
113// A builtin function is defined by writing:
114//
115// BUILTIN(name) {
116// ...
117// }
Steve Blocka7e24c12009-10-30 11:49:00 +0000118//
Leon Clarkee46be812010-01-19 14:06:41 +0000119// In the body of the builtin function the arguments can be accessed
120// through the BuiltinArguments object args.
Steve Blocka7e24c12009-10-30 11:49:00 +0000121
Leon Clarkee46be812010-01-19 14:06:41 +0000122#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +0000123
Leon Clarkee46be812010-01-19 14:06:41 +0000124#define BUILTIN(name) \
125 static Object* Builtin_Impl_##name(name##ArgumentsType args); \
126 static Object* Builtin_##name(name##ArgumentsType args) { \
127 args.Verify(); \
128 return Builtin_Impl_##name(args); \
129 } \
130 static Object* Builtin_Impl_##name(name##ArgumentsType args)
Steve Blocka7e24c12009-10-30 11:49:00 +0000131
Leon Clarkee46be812010-01-19 14:06:41 +0000132#else // For release mode.
Steve Blocka7e24c12009-10-30 11:49:00 +0000133
Leon Clarkee46be812010-01-19 14:06:41 +0000134#define BUILTIN(name) \
135 static Object* Builtin_##name(name##ArgumentsType args)
136
137#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000138
139
140static inline bool CalledAsConstructor() {
141#ifdef DEBUG
142 // Calculate the result using a full stack frame iterator and check
143 // that the state of the stack is as we assume it to be in the
144 // code below.
145 StackFrameIterator it;
146 ASSERT(it.frame()->is_exit());
147 it.Advance();
148 StackFrame* frame = it.frame();
149 bool reference_result = frame->is_construct();
150#endif
151 Address fp = Top::c_entry_fp(Top::GetCurrentThread());
152 // Because we know fp points to an exit frame we can use the relevant
153 // part of ExitFrame::ComputeCallerState directly.
154 const int kCallerOffset = ExitFrameConstants::kCallerFPOffset;
155 Address caller_fp = Memory::Address_at(fp + kCallerOffset);
156 // This inlines the part of StackFrame::ComputeType that grabs the
157 // type of the current frame. Note that StackFrame::ComputeType
158 // has been specialized for each architecture so if any one of them
159 // changes this code has to be changed as well.
160 const int kMarkerOffset = StandardFrameConstants::kMarkerOffset;
161 const Smi* kConstructMarker = Smi::FromInt(StackFrame::CONSTRUCT);
162 Object* marker = Memory::Object_at(caller_fp + kMarkerOffset);
163 bool result = (marker == kConstructMarker);
164 ASSERT_EQ(result, reference_result);
165 return result;
166}
167
168// ----------------------------------------------------------------------------
169
170
171Handle<Code> Builtins::GetCode(JavaScript id, bool* resolved) {
172 Code* code = Builtins::builtin(Builtins::Illegal);
173 *resolved = false;
174
175 if (Top::context() != NULL) {
176 Object* object = Top::builtins()->javascript_builtin(id);
177 if (object->IsJSFunction()) {
Leon Clarke4515c472010-02-03 11:58:03 +0000178 Handle<SharedFunctionInfo> shared(JSFunction::cast(object)->shared());
Steve Blocka7e24c12009-10-30 11:49:00 +0000179 // Make sure the number of parameters match the formal parameter count.
Leon Clarke4515c472010-02-03 11:58:03 +0000180 ASSERT(shared->formal_parameter_count() ==
Steve Blocka7e24c12009-10-30 11:49:00 +0000181 Builtins::GetArgumentsCount(id));
Leon Clarke4515c472010-02-03 11:58:03 +0000182 if (EnsureCompiled(shared, CLEAR_EXCEPTION)) {
183 code = shared->code();
Steve Blocka7e24c12009-10-30 11:49:00 +0000184 *resolved = true;
185 }
186 }
187 }
188
189 return Handle<Code>(code);
190}
191
192
193BUILTIN(Illegal) {
194 UNREACHABLE();
Leon Clarkee46be812010-01-19 14:06:41 +0000195 return Heap::undefined_value(); // Make compiler happy.
Steve Blocka7e24c12009-10-30 11:49:00 +0000196}
Steve Blocka7e24c12009-10-30 11:49:00 +0000197
198
199BUILTIN(EmptyFunction) {
Leon Clarkee46be812010-01-19 14:06:41 +0000200 return Heap::undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000201}
Steve Blocka7e24c12009-10-30 11:49:00 +0000202
203
204BUILTIN(ArrayCodeGeneric) {
205 Counters::array_function_runtime.Increment();
206
207 JSArray* array;
208 if (CalledAsConstructor()) {
Leon Clarkee46be812010-01-19 14:06:41 +0000209 array = JSArray::cast(*args.receiver());
Steve Blocka7e24c12009-10-30 11:49:00 +0000210 } else {
211 // Allocate the JS Array
212 JSFunction* constructor =
213 Top::context()->global_context()->array_function();
214 Object* obj = Heap::AllocateJSObject(constructor);
215 if (obj->IsFailure()) return obj;
216 array = JSArray::cast(obj);
217 }
218
219 // 'array' now contains the JSArray we should initialize.
220
221 // Optimize the case where there is one argument and the argument is a
222 // small smi.
223 if (args.length() == 2) {
224 Object* obj = args[1];
225 if (obj->IsSmi()) {
226 int len = Smi::cast(obj)->value();
227 if (len >= 0 && len < JSObject::kInitialMaxFastElementArray) {
228 Object* obj = Heap::AllocateFixedArrayWithHoles(len);
229 if (obj->IsFailure()) return obj;
230 array->SetContent(FixedArray::cast(obj));
231 return array;
232 }
233 }
234 // Take the argument as the length.
235 obj = array->Initialize(0);
236 if (obj->IsFailure()) return obj;
237 return array->SetElementsLength(args[1]);
238 }
239
240 // Optimize the case where there are no parameters passed.
241 if (args.length() == 1) {
242 return array->Initialize(JSArray::kPreallocatedArrayElements);
243 }
244
245 // Take the arguments as elements.
246 int number_of_elements = args.length() - 1;
247 Smi* len = Smi::FromInt(number_of_elements);
248 Object* obj = Heap::AllocateFixedArrayWithHoles(len->value());
249 if (obj->IsFailure()) return obj;
Leon Clarke4515c472010-02-03 11:58:03 +0000250
251 AssertNoAllocation no_gc;
Steve Blocka7e24c12009-10-30 11:49:00 +0000252 FixedArray* elms = FixedArray::cast(obj);
Leon Clarke4515c472010-02-03 11:58:03 +0000253 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
Steve Blocka7e24c12009-10-30 11:49:00 +0000254 // Fill in the content
255 for (int index = 0; index < number_of_elements; index++) {
256 elms->set(index, args[index+1], mode);
257 }
258
259 // Set length and elements on the array.
260 array->set_elements(FixedArray::cast(obj));
Leon Clarke4515c472010-02-03 11:58:03 +0000261 array->set_length(len);
Steve Blocka7e24c12009-10-30 11:49:00 +0000262
263 return array;
264}
Steve Blocka7e24c12009-10-30 11:49:00 +0000265
266
267BUILTIN(ArrayPush) {
Leon Clarkee46be812010-01-19 14:06:41 +0000268 JSArray* array = JSArray::cast(*args.receiver());
Steve Blocka7e24c12009-10-30 11:49:00 +0000269 ASSERT(array->HasFastElements());
270
271 // Make sure we have space for the elements.
272 int len = Smi::cast(array->length())->value();
273
274 // Set new length.
275 int new_length = len + args.length() - 1;
276 FixedArray* elms = FixedArray::cast(array->elements());
277
278 if (new_length <= elms->length()) {
279 // Backing storage has extra space for the provided values.
280 for (int index = 0; index < args.length() - 1; index++) {
281 elms->set(index + len, args[index+1]);
282 }
283 } else {
284 // New backing storage is needed.
285 int capacity = new_length + (new_length >> 1) + 16;
286 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity);
287 if (obj->IsFailure()) return obj;
Leon Clarke4515c472010-02-03 11:58:03 +0000288
289 AssertNoAllocation no_gc;
Steve Blocka7e24c12009-10-30 11:49:00 +0000290 FixedArray* new_elms = FixedArray::cast(obj);
Leon Clarke4515c472010-02-03 11:58:03 +0000291 WriteBarrierMode mode = new_elms->GetWriteBarrierMode(no_gc);
Steve Blocka7e24c12009-10-30 11:49:00 +0000292 // Fill out the new array with old elements.
293 for (int i = 0; i < len; i++) new_elms->set(i, elms->get(i), mode);
294 // Add the provided values.
295 for (int index = 0; index < args.length() - 1; index++) {
296 new_elms->set(index + len, args[index+1], mode);
297 }
298 // Set the new backing storage.
299 array->set_elements(new_elms);
300 }
301 // Set the length.
Leon Clarke4515c472010-02-03 11:58:03 +0000302 array->set_length(Smi::FromInt(new_length));
Steve Blocka7e24c12009-10-30 11:49:00 +0000303 return array->length();
304}
Steve Blocka7e24c12009-10-30 11:49:00 +0000305
306
307BUILTIN(ArrayPop) {
Leon Clarkee46be812010-01-19 14:06:41 +0000308 JSArray* array = JSArray::cast(*args.receiver());
Steve Blocka7e24c12009-10-30 11:49:00 +0000309 ASSERT(array->HasFastElements());
310 Object* undefined = Heap::undefined_value();
311
312 int len = Smi::cast(array->length())->value();
313 if (len == 0) return undefined;
314
315 // Get top element
316 FixedArray* elms = FixedArray::cast(array->elements());
317 Object* top = elms->get(len - 1);
318
319 // Set the length.
Leon Clarke4515c472010-02-03 11:58:03 +0000320 array->set_length(Smi::FromInt(len - 1));
Steve Blocka7e24c12009-10-30 11:49:00 +0000321
322 if (!top->IsTheHole()) {
323 // Delete the top element.
324 elms->set_the_hole(len - 1);
325 return top;
326 }
327
328 // Remember to check the prototype chain.
329 JSFunction* array_function =
330 Top::context()->global_context()->array_function();
331 JSObject* prototype = JSObject::cast(array_function->prototype());
332 top = prototype->GetElement(len - 1);
333
334 return top;
335}
Steve Blocka7e24c12009-10-30 11:49:00 +0000336
337
338// -----------------------------------------------------------------------------
339//
340
341
342// Returns the holder JSObject if the function can legally be called
343// with this receiver. Returns Heap::null_value() if the call is
344// illegal. Any arguments that don't fit the expected type is
345// overwritten with undefined. Arguments that do fit the expected
346// type is overwritten with the object in the prototype chain that
347// actually has that type.
348static inline Object* TypeCheck(int argc,
349 Object** argv,
350 FunctionTemplateInfo* info) {
351 Object* recv = argv[0];
352 Object* sig_obj = info->signature();
353 if (sig_obj->IsUndefined()) return recv;
354 SignatureInfo* sig = SignatureInfo::cast(sig_obj);
355 // If necessary, check the receiver
356 Object* recv_type = sig->receiver();
357
358 Object* holder = recv;
359 if (!recv_type->IsUndefined()) {
360 for (; holder != Heap::null_value(); holder = holder->GetPrototype()) {
361 if (holder->IsInstanceOf(FunctionTemplateInfo::cast(recv_type))) {
362 break;
363 }
364 }
365 if (holder == Heap::null_value()) return holder;
366 }
367 Object* args_obj = sig->args();
368 // If there is no argument signature we're done
369 if (args_obj->IsUndefined()) return holder;
370 FixedArray* args = FixedArray::cast(args_obj);
371 int length = args->length();
372 if (argc <= length) length = argc - 1;
373 for (int i = 0; i < length; i++) {
374 Object* argtype = args->get(i);
375 if (argtype->IsUndefined()) continue;
376 Object** arg = &argv[-1 - i];
377 Object* current = *arg;
378 for (; current != Heap::null_value(); current = current->GetPrototype()) {
379 if (current->IsInstanceOf(FunctionTemplateInfo::cast(argtype))) {
380 *arg = current;
381 break;
382 }
383 }
384 if (current == Heap::null_value()) *arg = Heap::undefined_value();
385 }
386 return holder;
387}
388
389
Leon Clarkee46be812010-01-19 14:06:41 +0000390template <bool is_construct>
391static Object* HandleApiCallHelper(
392 BuiltinArguments<NEEDS_CALLED_FUNCTION> args) {
393 ASSERT(is_construct == CalledAsConstructor());
Steve Blocka7e24c12009-10-30 11:49:00 +0000394
Leon Clarkee46be812010-01-19 14:06:41 +0000395 HandleScope scope;
396 Handle<JSFunction> function = args.called_function();
Steve Blocka7e24c12009-10-30 11:49:00 +0000397
398 if (is_construct) {
399 Handle<FunctionTemplateInfo> desc =
400 Handle<FunctionTemplateInfo>(
401 FunctionTemplateInfo::cast(function->shared()->function_data()));
402 bool pending_exception = false;
Leon Clarkee46be812010-01-19 14:06:41 +0000403 Factory::ConfigureInstance(desc, Handle<JSObject>::cast(args.receiver()),
Steve Blocka7e24c12009-10-30 11:49:00 +0000404 &pending_exception);
405 ASSERT(Top::has_pending_exception() == pending_exception);
406 if (pending_exception) return Failure::Exception();
407 }
408
409 FunctionTemplateInfo* fun_data =
410 FunctionTemplateInfo::cast(function->shared()->function_data());
411 Object* raw_holder = TypeCheck(args.length(), &args[0], fun_data);
412
413 if (raw_holder->IsNull()) {
414 // This function cannot be called with the given receiver. Abort!
415 Handle<Object> obj =
416 Factory::NewTypeError("illegal_invocation", HandleVector(&function, 1));
417 return Top::Throw(*obj);
418 }
419
420 Object* raw_call_data = fun_data->call_code();
421 if (!raw_call_data->IsUndefined()) {
422 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
423 Object* callback_obj = call_data->callback();
424 v8::InvocationCallback callback =
425 v8::ToCData<v8::InvocationCallback>(callback_obj);
426 Object* data_obj = call_data->data();
427 Object* result;
428
Steve Blocka7e24c12009-10-30 11:49:00 +0000429 Handle<Object> data_handle(data_obj);
430 v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle);
431 ASSERT(raw_holder->IsJSObject());
432 v8::Local<v8::Function> callee = v8::Utils::ToLocal(function);
433 Handle<JSObject> holder_handle(JSObject::cast(raw_holder));
434 v8::Local<v8::Object> holder = v8::Utils::ToLocal(holder_handle);
Leon Clarkee46be812010-01-19 14:06:41 +0000435 LOG(ApiObjectAccess("call", JSObject::cast(*args.receiver())));
Steve Blocka7e24c12009-10-30 11:49:00 +0000436 v8::Arguments new_args = v8::ImplementationUtilities::NewArguments(
437 data,
438 holder,
439 callee,
440 is_construct,
441 reinterpret_cast<void**>(&args[0] - 1),
442 args.length() - 1);
443
444 v8::Handle<v8::Value> value;
445 {
446 // Leaving JavaScript.
447 VMState state(EXTERNAL);
Steve Blockd0582a62009-12-15 09:54:21 +0000448#ifdef ENABLE_LOGGING_AND_PROFILING
449 state.set_external_callback(v8::ToCData<Address>(callback_obj));
450#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000451 value = callback(new_args);
452 }
453 if (value.IsEmpty()) {
454 result = Heap::undefined_value();
455 } else {
456 result = *reinterpret_cast<Object**>(*value);
457 }
458
459 RETURN_IF_SCHEDULED_EXCEPTION();
460 if (!is_construct || result->IsJSObject()) return result;
461 }
462
Leon Clarkee46be812010-01-19 14:06:41 +0000463 return *args.receiver();
Steve Blocka7e24c12009-10-30 11:49:00 +0000464}
Leon Clarkee46be812010-01-19 14:06:41 +0000465
466
467BUILTIN(HandleApiCall) {
468 return HandleApiCallHelper<false>(args);
469}
470
471
472BUILTIN(HandleApiCallConstruct) {
473 return HandleApiCallHelper<true>(args);
474}
Steve Blocka7e24c12009-10-30 11:49:00 +0000475
476
477// Helper function to handle calls to non-function objects created through the
478// API. The object can be called as either a constructor (using new) or just as
479// a function (without new).
Leon Clarkee46be812010-01-19 14:06:41 +0000480static Object* HandleApiCallAsFunctionOrConstructor(
481 bool is_construct_call,
482 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000483 // Non-functions are never called as constructors. Even if this is an object
484 // called as a constructor the delegate call is not a construct call.
485 ASSERT(!CalledAsConstructor());
486
487 Handle<Object> receiver = args.at<Object>(0);
488
489 // Get the object called.
Leon Clarkee46be812010-01-19 14:06:41 +0000490 JSObject* obj = JSObject::cast(*args.receiver());
Steve Blocka7e24c12009-10-30 11:49:00 +0000491
492 // Get the invocation callback from the function descriptor that was
493 // used to create the called object.
494 ASSERT(obj->map()->has_instance_call_handler());
495 JSFunction* constructor = JSFunction::cast(obj->map()->constructor());
496 Object* template_info = constructor->shared()->function_data();
497 Object* handler =
498 FunctionTemplateInfo::cast(template_info)->instance_call_handler();
499 ASSERT(!handler->IsUndefined());
500 CallHandlerInfo* call_data = CallHandlerInfo::cast(handler);
501 Object* callback_obj = call_data->callback();
502 v8::InvocationCallback callback =
503 v8::ToCData<v8::InvocationCallback>(callback_obj);
504
505 // Get the data for the call and perform the callback.
506 Object* data_obj = call_data->data();
507 Object* result;
508 { HandleScope scope;
509 v8::Local<v8::Object> self =
Leon Clarkee46be812010-01-19 14:06:41 +0000510 v8::Utils::ToLocal(Handle<JSObject>::cast(args.receiver()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000511 Handle<Object> data_handle(data_obj);
512 v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle);
513 Handle<JSFunction> callee_handle(constructor);
514 v8::Local<v8::Function> callee = v8::Utils::ToLocal(callee_handle);
Leon Clarkee46be812010-01-19 14:06:41 +0000515 LOG(ApiObjectAccess("call non-function", JSObject::cast(*args.receiver())));
Steve Blocka7e24c12009-10-30 11:49:00 +0000516 v8::Arguments new_args = v8::ImplementationUtilities::NewArguments(
517 data,
518 self,
519 callee,
520 is_construct_call,
521 reinterpret_cast<void**>(&args[0] - 1),
522 args.length() - 1);
523 v8::Handle<v8::Value> value;
524 {
525 // Leaving JavaScript.
526 VMState state(EXTERNAL);
Steve Blockd0582a62009-12-15 09:54:21 +0000527#ifdef ENABLE_LOGGING_AND_PROFILING
528 state.set_external_callback(v8::ToCData<Address>(callback_obj));
529#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000530 value = callback(new_args);
531 }
532 if (value.IsEmpty()) {
533 result = Heap::undefined_value();
534 } else {
535 result = *reinterpret_cast<Object**>(*value);
536 }
537 }
538 // Check for exceptions and return result.
539 RETURN_IF_SCHEDULED_EXCEPTION();
540 return result;
541}
542
543
544// Handle calls to non-function objects created through the API. This delegate
545// function is used when the call is a normal function call.
546BUILTIN(HandleApiCallAsFunction) {
547 return HandleApiCallAsFunctionOrConstructor(false, args);
548}
Steve Blocka7e24c12009-10-30 11:49:00 +0000549
550
551// Handle calls to non-function objects created through the API. This delegate
552// function is used when the call is a construct call.
553BUILTIN(HandleApiCallAsConstructor) {
554 return HandleApiCallAsFunctionOrConstructor(true, args);
555}
Steve Blocka7e24c12009-10-30 11:49:00 +0000556
557
558static void Generate_LoadIC_ArrayLength(MacroAssembler* masm) {
559 LoadIC::GenerateArrayLength(masm);
560}
561
562
563static void Generate_LoadIC_StringLength(MacroAssembler* masm) {
564 LoadIC::GenerateStringLength(masm);
565}
566
567
568static void Generate_LoadIC_FunctionPrototype(MacroAssembler* masm) {
569 LoadIC::GenerateFunctionPrototype(masm);
570}
571
572
573static void Generate_LoadIC_Initialize(MacroAssembler* masm) {
574 LoadIC::GenerateInitialize(masm);
575}
576
577
578static void Generate_LoadIC_PreMonomorphic(MacroAssembler* masm) {
579 LoadIC::GeneratePreMonomorphic(masm);
580}
581
582
583static void Generate_LoadIC_Miss(MacroAssembler* masm) {
584 LoadIC::GenerateMiss(masm);
585}
586
587
588static void Generate_LoadIC_Megamorphic(MacroAssembler* masm) {
589 LoadIC::GenerateMegamorphic(masm);
590}
591
592
593static void Generate_LoadIC_Normal(MacroAssembler* masm) {
594 LoadIC::GenerateNormal(masm);
595}
596
597
598static void Generate_KeyedLoadIC_Initialize(MacroAssembler* masm) {
599 KeyedLoadIC::GenerateInitialize(masm);
600}
601
602
603static void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
604 KeyedLoadIC::GenerateMiss(masm);
605}
606
607
608static void Generate_KeyedLoadIC_Generic(MacroAssembler* masm) {
609 KeyedLoadIC::GenerateGeneric(masm);
610}
611
612
Leon Clarkee46be812010-01-19 14:06:41 +0000613static void Generate_KeyedLoadIC_String(MacroAssembler* masm) {
614 KeyedLoadIC::GenerateString(masm);
615}
616
617
Steve Block3ce2e202009-11-05 08:53:23 +0000618static void Generate_KeyedLoadIC_ExternalByteArray(MacroAssembler* masm) {
619 KeyedLoadIC::GenerateExternalArray(masm, kExternalByteArray);
620}
621
622
623static void Generate_KeyedLoadIC_ExternalUnsignedByteArray(
624 MacroAssembler* masm) {
625 KeyedLoadIC::GenerateExternalArray(masm, kExternalUnsignedByteArray);
626}
627
628
629static void Generate_KeyedLoadIC_ExternalShortArray(MacroAssembler* masm) {
630 KeyedLoadIC::GenerateExternalArray(masm, kExternalShortArray);
631}
632
633
634static void Generate_KeyedLoadIC_ExternalUnsignedShortArray(
635 MacroAssembler* masm) {
636 KeyedLoadIC::GenerateExternalArray(masm, kExternalUnsignedShortArray);
637}
638
639
640static void Generate_KeyedLoadIC_ExternalIntArray(MacroAssembler* masm) {
641 KeyedLoadIC::GenerateExternalArray(masm, kExternalIntArray);
642}
643
644
645static void Generate_KeyedLoadIC_ExternalUnsignedIntArray(
646 MacroAssembler* masm) {
647 KeyedLoadIC::GenerateExternalArray(masm, kExternalUnsignedIntArray);
648}
649
650
651static void Generate_KeyedLoadIC_ExternalFloatArray(MacroAssembler* masm) {
652 KeyedLoadIC::GenerateExternalArray(masm, kExternalFloatArray);
653}
654
655
Steve Blocka7e24c12009-10-30 11:49:00 +0000656static void Generate_KeyedLoadIC_PreMonomorphic(MacroAssembler* masm) {
657 KeyedLoadIC::GeneratePreMonomorphic(masm);
658}
659
660
661static void Generate_StoreIC_Initialize(MacroAssembler* masm) {
662 StoreIC::GenerateInitialize(masm);
663}
664
665
666static void Generate_StoreIC_Miss(MacroAssembler* masm) {
667 StoreIC::GenerateMiss(masm);
668}
669
670
671static void Generate_StoreIC_ExtendStorage(MacroAssembler* masm) {
672 StoreIC::GenerateExtendStorage(masm);
673}
674
675static void Generate_StoreIC_Megamorphic(MacroAssembler* masm) {
676 StoreIC::GenerateMegamorphic(masm);
677}
678
679
680static void Generate_KeyedStoreIC_Generic(MacroAssembler* masm) {
681 KeyedStoreIC::GenerateGeneric(masm);
682}
683
684
Steve Block3ce2e202009-11-05 08:53:23 +0000685static void Generate_KeyedStoreIC_ExternalByteArray(MacroAssembler* masm) {
686 KeyedStoreIC::GenerateExternalArray(masm, kExternalByteArray);
687}
688
689
690static void Generate_KeyedStoreIC_ExternalUnsignedByteArray(
691 MacroAssembler* masm) {
692 KeyedStoreIC::GenerateExternalArray(masm, kExternalUnsignedByteArray);
693}
694
695
696static void Generate_KeyedStoreIC_ExternalShortArray(MacroAssembler* masm) {
697 KeyedStoreIC::GenerateExternalArray(masm, kExternalShortArray);
698}
699
700
701static void Generate_KeyedStoreIC_ExternalUnsignedShortArray(
702 MacroAssembler* masm) {
703 KeyedStoreIC::GenerateExternalArray(masm, kExternalUnsignedShortArray);
704}
705
706
707static void Generate_KeyedStoreIC_ExternalIntArray(MacroAssembler* masm) {
708 KeyedStoreIC::GenerateExternalArray(masm, kExternalIntArray);
709}
710
711
712static void Generate_KeyedStoreIC_ExternalUnsignedIntArray(
713 MacroAssembler* masm) {
714 KeyedStoreIC::GenerateExternalArray(masm, kExternalUnsignedIntArray);
715}
716
717
718static void Generate_KeyedStoreIC_ExternalFloatArray(MacroAssembler* masm) {
719 KeyedStoreIC::GenerateExternalArray(masm, kExternalFloatArray);
720}
721
722
Steve Blocka7e24c12009-10-30 11:49:00 +0000723static void Generate_KeyedStoreIC_ExtendStorage(MacroAssembler* masm) {
724 KeyedStoreIC::GenerateExtendStorage(masm);
725}
726
727
728static void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
729 KeyedStoreIC::GenerateMiss(masm);
730}
731
732
733static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) {
734 KeyedStoreIC::GenerateInitialize(masm);
735}
736
737
738#ifdef ENABLE_DEBUGGER_SUPPORT
739static void Generate_LoadIC_DebugBreak(MacroAssembler* masm) {
740 Debug::GenerateLoadICDebugBreak(masm);
741}
742
743
744static void Generate_StoreIC_DebugBreak(MacroAssembler* masm) {
745 Debug::GenerateStoreICDebugBreak(masm);
746}
747
748
749static void Generate_KeyedLoadIC_DebugBreak(MacroAssembler* masm) {
750 Debug::GenerateKeyedLoadICDebugBreak(masm);
751}
752
753
754static void Generate_KeyedStoreIC_DebugBreak(MacroAssembler* masm) {
755 Debug::GenerateKeyedStoreICDebugBreak(masm);
756}
757
758
759static void Generate_ConstructCall_DebugBreak(MacroAssembler* masm) {
760 Debug::GenerateConstructCallDebugBreak(masm);
761}
762
763
764static void Generate_Return_DebugBreak(MacroAssembler* masm) {
765 Debug::GenerateReturnDebugBreak(masm);
766}
767
768
769static void Generate_StubNoRegisters_DebugBreak(MacroAssembler* masm) {
770 Debug::GenerateStubNoRegistersDebugBreak(masm);
771}
772#endif
773
774Object* Builtins::builtins_[builtin_count] = { NULL, };
775const char* Builtins::names_[builtin_count] = { NULL, };
776
Leon Clarkee46be812010-01-19 14:06:41 +0000777#define DEF_ENUM_C(name, ignore) FUNCTION_ADDR(Builtin_##name),
Steve Blocka7e24c12009-10-30 11:49:00 +0000778 Address Builtins::c_functions_[cfunction_count] = {
779 BUILTIN_LIST_C(DEF_ENUM_C)
780 };
781#undef DEF_ENUM_C
782
783#define DEF_JS_NAME(name, ignore) #name,
784#define DEF_JS_ARGC(ignore, argc) argc,
785const char* Builtins::javascript_names_[id_count] = {
786 BUILTINS_LIST_JS(DEF_JS_NAME)
787};
788
789int Builtins::javascript_argc_[id_count] = {
790 BUILTINS_LIST_JS(DEF_JS_ARGC)
791};
792#undef DEF_JS_NAME
793#undef DEF_JS_ARGC
794
795static bool is_initialized = false;
796void Builtins::Setup(bool create_heap_objects) {
797 ASSERT(!is_initialized);
798
799 // Create a scope for the handles in the builtins.
800 HandleScope scope;
801
802 struct BuiltinDesc {
803 byte* generator;
804 byte* c_code;
805 const char* s_name; // name is only used for generating log information.
806 int name;
807 Code::Flags flags;
Leon Clarkee46be812010-01-19 14:06:41 +0000808 BuiltinExtraArguments extra_args;
Steve Blocka7e24c12009-10-30 11:49:00 +0000809 };
810
Leon Clarkee46be812010-01-19 14:06:41 +0000811#define DEF_FUNCTION_PTR_C(name, extra_args) \
812 { FUNCTION_ADDR(Generate_Adaptor), \
813 FUNCTION_ADDR(Builtin_##name), \
814 #name, \
815 c_##name, \
816 Code::ComputeFlags(Code::BUILTIN), \
817 extra_args \
Steve Blocka7e24c12009-10-30 11:49:00 +0000818 },
819
820#define DEF_FUNCTION_PTR_A(name, kind, state) \
821 { FUNCTION_ADDR(Generate_##name), \
822 NULL, \
823 #name, \
824 name, \
Leon Clarkee46be812010-01-19 14:06:41 +0000825 Code::ComputeFlags(Code::kind, NOT_IN_LOOP, state), \
826 NO_EXTRA_ARGUMENTS \
Steve Blocka7e24c12009-10-30 11:49:00 +0000827 },
828
829 // Define array of pointers to generators and C builtin functions.
830 static BuiltinDesc functions[] = {
831 BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
832 BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
833 BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
834 // Terminator:
Leon Clarkee46be812010-01-19 14:06:41 +0000835 { NULL, NULL, NULL, builtin_count, static_cast<Code::Flags>(0),
836 NO_EXTRA_ARGUMENTS }
Steve Blocka7e24c12009-10-30 11:49:00 +0000837 };
838
839#undef DEF_FUNCTION_PTR_C
840#undef DEF_FUNCTION_PTR_A
841
842 // For now we generate builtin adaptor code into a stack-allocated
843 // buffer, before copying it into individual code objects.
844 byte buffer[4*KB];
845
846 // Traverse the list of builtins and generate an adaptor in a
847 // separate code object for each one.
848 for (int i = 0; i < builtin_count; i++) {
849 if (create_heap_objects) {
850 MacroAssembler masm(buffer, sizeof buffer);
851 // Generate the code/adaptor.
Leon Clarkee46be812010-01-19 14:06:41 +0000852 typedef void (*Generator)(MacroAssembler*, int, BuiltinExtraArguments);
Steve Blocka7e24c12009-10-30 11:49:00 +0000853 Generator g = FUNCTION_CAST<Generator>(functions[i].generator);
854 // We pass all arguments to the generator, but it may not use all of
855 // them. This works because the first arguments are on top of the
856 // stack.
Leon Clarkee46be812010-01-19 14:06:41 +0000857 g(&masm, functions[i].name, functions[i].extra_args);
Steve Blocka7e24c12009-10-30 11:49:00 +0000858 // Move the code into the object heap.
859 CodeDesc desc;
860 masm.GetCode(&desc);
861 Code::Flags flags = functions[i].flags;
862 Object* code;
863 {
864 // During startup it's OK to always allocate and defer GC to later.
865 // This simplifies things because we don't need to retry.
866 AlwaysAllocateScope __scope__;
867 code = Heap::CreateCode(desc, NULL, flags, masm.CodeObject());
868 if (code->IsFailure()) {
869 v8::internal::V8::FatalProcessOutOfMemory("CreateCode");
870 }
871 }
872 // Add any unresolved jumps or calls to the fixup list in the
873 // bootstrapper.
874 Bootstrapper::AddFixup(Code::cast(code), &masm);
875 // Log the event and add the code to the builtins array.
876 LOG(CodeCreateEvent(Logger::BUILTIN_TAG,
877 Code::cast(code), functions[i].s_name));
878 builtins_[i] = code;
879#ifdef ENABLE_DISASSEMBLER
880 if (FLAG_print_builtin_code) {
881 PrintF("Builtin: %s\n", functions[i].s_name);
882 Code::cast(code)->Disassemble(functions[i].s_name);
883 PrintF("\n");
884 }
885#endif
886 } else {
887 // Deserializing. The values will be filled in during IterateBuiltins.
888 builtins_[i] = NULL;
889 }
890 names_[i] = functions[i].s_name;
891 }
892
893 // Mark as initialized.
894 is_initialized = true;
895}
896
897
898void Builtins::TearDown() {
899 is_initialized = false;
900}
901
902
903void Builtins::IterateBuiltins(ObjectVisitor* v) {
904 v->VisitPointers(&builtins_[0], &builtins_[0] + builtin_count);
905}
906
907
908const char* Builtins::Lookup(byte* pc) {
909 if (is_initialized) { // may be called during initialization (disassembler!)
910 for (int i = 0; i < builtin_count; i++) {
911 Code* entry = Code::cast(builtins_[i]);
912 if (entry->contains(pc)) {
913 return names_[i];
914 }
915 }
916 }
917 return NULL;
918}
919
920
921} } // namespace v8::internal