OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 18 matching lines...) Expand all Loading... |
29 | 29 |
30 #include "api.h" | 30 #include "api.h" |
31 #include "arguments.h" | 31 #include "arguments.h" |
32 #include "bootstrapper.h" | 32 #include "bootstrapper.h" |
33 #include "builtins.h" | 33 #include "builtins.h" |
34 #include "ic-inl.h" | 34 #include "ic-inl.h" |
35 | 35 |
36 namespace v8 { | 36 namespace v8 { |
37 namespace internal { | 37 namespace internal { |
38 | 38 |
| 39 namespace { |
| 40 |
| 41 // Arguments object passed to C++ builtins. |
| 42 template <BuiltinExtraArguments extra_args> |
| 43 class BuiltinArguments : public Arguments { |
| 44 public: |
| 45 Object*& operator[] (int index) { |
| 46 ASSERT(index < length()); |
| 47 return Arguments::operator[](index); |
| 48 } |
| 49 |
| 50 template <class S> Handle<S> at(int index) { |
| 51 ASSERT(index < length()); |
| 52 return Arguments::at<S>(index); |
| 53 } |
| 54 |
| 55 Handle<Object> receiver() { |
| 56 return Arguments::at<Object>(0); |
| 57 } |
| 58 |
| 59 Handle<JSFunction> called_function() { |
| 60 STATIC_ASSERT(extra_args == NEEDS_CALLED_FUNCTION); |
| 61 return Arguments::at<JSFunction>(Arguments::length() - 1); |
| 62 } |
| 63 |
| 64 // Gets the total number of arguments including the receiver (but |
| 65 // excluding extra arguments). |
| 66 int length() const { |
| 67 STATIC_ASSERT(extra_args == NO_EXTRA_ARGUMENTS); |
| 68 return Arguments::length(); |
| 69 } |
| 70 |
| 71 #ifdef DEBUG |
| 72 void Verify() { |
| 73 // Check we have at least the receiver. |
| 74 ASSERT(Arguments::length() >= 1); |
| 75 } |
| 76 #endif |
| 77 }; |
| 78 |
| 79 |
| 80 // Specialize BuiltinArguments for the called function extra argument. |
| 81 |
| 82 template <> |
| 83 int BuiltinArguments<NEEDS_CALLED_FUNCTION>::length() const { |
| 84 return Arguments::length() - 1; |
| 85 } |
| 86 |
| 87 #ifdef DEBUG |
| 88 template <> |
| 89 void BuiltinArguments<NEEDS_CALLED_FUNCTION>::Verify() { |
| 90 // Check we have at least the receiver and the called function. |
| 91 ASSERT(Arguments::length() >= 2); |
| 92 // Make sure cast to JSFunction succeeds. |
| 93 called_function(); |
| 94 } |
| 95 #endif |
| 96 |
| 97 |
| 98 #define DEF_ARG_TYPE(name, spec) \ |
| 99 typedef BuiltinArguments<spec> name##ArgumentsType; |
| 100 BUILTIN_LIST_C(DEF_ARG_TYPE) |
| 101 #undef DEF_ARG_TYPE |
| 102 |
| 103 } // namespace |
| 104 |
| 105 |
39 // ---------------------------------------------------------------------------- | 106 // ---------------------------------------------------------------------------- |
40 // Support macros for defining builtins in C. | 107 // Support macro for defining builtins in C++. |
41 // ---------------------------------------------------------------------------- | 108 // ---------------------------------------------------------------------------- |
42 // | 109 // |
43 // A builtin function is defined by writing: | 110 // A builtin function is defined by writing: |
44 // | 111 // |
45 // BUILTIN(name) { | 112 // BUILTIN(name) { |
46 // ... | 113 // ... |
47 // } | 114 // } |
48 // BUILTIN_END | |
49 // | 115 // |
50 // In the body of the builtin function, the variable 'receiver' is visible. | 116 // In the body of the builtin function the arguments can be accessed |
51 // The arguments can be accessed through the Arguments object args. | 117 // through the BuiltinArguments 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 | 118 |
| 119 #ifdef DEBUG |
60 | 120 |
61 // TODO(428): We should consider passing whether or not the | 121 #define BUILTIN(name) \ |
62 // builtin was invoked as a constructor as part of the | 122 static Object* Builtin_Impl_##name(name##ArgumentsType args); \ |
63 // arguments. Maybe we also want to pass the called function? | 123 static Object* Builtin_##name(name##ArgumentsType args) { \ |
64 #define BUILTIN(name) \ | 124 args.Verify(); \ |
65 static Object* Builtin_##name(Arguments args) { \ | 125 return Builtin_Impl_##name(args); \ |
66 Handle<Object> receiver = args.at<Object>(0); | 126 } \ |
| 127 static Object* Builtin_Impl_##name(name##ArgumentsType args) |
67 | 128 |
| 129 #else // For release mode. |
68 | 130 |
69 #define BUILTIN_END \ | 131 #define BUILTIN(name) \ |
70 return Heap::undefined_value(); \ | 132 static Object* Builtin_##name(name##ArgumentsType args) |
71 } | 133 |
| 134 #endif |
72 | 135 |
73 | 136 |
74 static inline bool CalledAsConstructor() { | 137 static inline bool CalledAsConstructor() { |
75 #ifdef DEBUG | 138 #ifdef DEBUG |
76 // Calculate the result using a full stack frame iterator and check | 139 // 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 | 140 // that the state of the stack is as we assume it to be in the |
78 // code below. | 141 // code below. |
79 StackFrameIterator it; | 142 StackFrameIterator it; |
80 ASSERT(it.frame()->is_exit()); | 143 ASSERT(it.frame()->is_exit()); |
81 it.Advance(); | 144 it.Advance(); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 } | 182 } |
120 } | 183 } |
121 } | 184 } |
122 | 185 |
123 return Handle<Code>(code); | 186 return Handle<Code>(code); |
124 } | 187 } |
125 | 188 |
126 | 189 |
127 BUILTIN(Illegal) { | 190 BUILTIN(Illegal) { |
128 UNREACHABLE(); | 191 UNREACHABLE(); |
| 192 return Heap::undefined_value(); // Make compiler happy. |
129 } | 193 } |
130 BUILTIN_END | |
131 | 194 |
132 | 195 |
133 BUILTIN(EmptyFunction) { | 196 BUILTIN(EmptyFunction) { |
| 197 return Heap::undefined_value(); |
134 } | 198 } |
135 BUILTIN_END | |
136 | 199 |
137 | 200 |
138 BUILTIN(ArrayCodeGeneric) { | 201 BUILTIN(ArrayCodeGeneric) { |
139 Counters::array_function_runtime.Increment(); | 202 Counters::array_function_runtime.Increment(); |
140 | 203 |
141 JSArray* array; | 204 JSArray* array; |
142 if (CalledAsConstructor()) { | 205 if (CalledAsConstructor()) { |
143 array = JSArray::cast(*receiver); | 206 array = JSArray::cast(*args.receiver()); |
144 } else { | 207 } else { |
145 // Allocate the JS Array | 208 // Allocate the JS Array |
146 JSFunction* constructor = | 209 JSFunction* constructor = |
147 Top::context()->global_context()->array_function(); | 210 Top::context()->global_context()->array_function(); |
148 Object* obj = Heap::AllocateJSObject(constructor); | 211 Object* obj = Heap::AllocateJSObject(constructor); |
149 if (obj->IsFailure()) return obj; | 212 if (obj->IsFailure()) return obj; |
150 array = JSArray::cast(obj); | 213 array = JSArray::cast(obj); |
151 } | 214 } |
152 | 215 |
153 // 'array' now contains the JSArray we should initialize. | 216 // 'array' now contains the JSArray we should initialize. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 for (int index = 0; index < number_of_elements; index++) { | 250 for (int index = 0; index < number_of_elements; index++) { |
188 elms->set(index, args[index+1], mode); | 251 elms->set(index, args[index+1], mode); |
189 } | 252 } |
190 | 253 |
191 // Set length and elements on the array. | 254 // Set length and elements on the array. |
192 array->set_elements(FixedArray::cast(obj)); | 255 array->set_elements(FixedArray::cast(obj)); |
193 array->set_length(len, SKIP_WRITE_BARRIER); | 256 array->set_length(len, SKIP_WRITE_BARRIER); |
194 | 257 |
195 return array; | 258 return array; |
196 } | 259 } |
197 BUILTIN_END | |
198 | 260 |
199 | 261 |
200 BUILTIN(ArrayPush) { | 262 BUILTIN(ArrayPush) { |
201 JSArray* array = JSArray::cast(*receiver); | 263 JSArray* array = JSArray::cast(*args.receiver()); |
202 ASSERT(array->HasFastElements()); | 264 ASSERT(array->HasFastElements()); |
203 | 265 |
204 // Make sure we have space for the elements. | 266 // Make sure we have space for the elements. |
205 int len = Smi::cast(array->length())->value(); | 267 int len = Smi::cast(array->length())->value(); |
206 | 268 |
207 // Set new length. | 269 // Set new length. |
208 int new_length = len + args.length() - 1; | 270 int new_length = len + args.length() - 1; |
209 FixedArray* elms = FixedArray::cast(array->elements()); | 271 FixedArray* elms = FixedArray::cast(array->elements()); |
210 | 272 |
211 if (new_length <= elms->length()) { | 273 if (new_length <= elms->length()) { |
(...skipping 14 matching lines...) Expand all Loading... |
226 for (int index = 0; index < args.length() - 1; index++) { | 288 for (int index = 0; index < args.length() - 1; index++) { |
227 new_elms->set(index + len, args[index+1], mode); | 289 new_elms->set(index + len, args[index+1], mode); |
228 } | 290 } |
229 // Set the new backing storage. | 291 // Set the new backing storage. |
230 array->set_elements(new_elms); | 292 array->set_elements(new_elms); |
231 } | 293 } |
232 // Set the length. | 294 // Set the length. |
233 array->set_length(Smi::FromInt(new_length), SKIP_WRITE_BARRIER); | 295 array->set_length(Smi::FromInt(new_length), SKIP_WRITE_BARRIER); |
234 return array->length(); | 296 return array->length(); |
235 } | 297 } |
236 BUILTIN_END | |
237 | 298 |
238 | 299 |
239 BUILTIN(ArrayPop) { | 300 BUILTIN(ArrayPop) { |
240 JSArray* array = JSArray::cast(*receiver); | 301 JSArray* array = JSArray::cast(*args.receiver()); |
241 ASSERT(array->HasFastElements()); | 302 ASSERT(array->HasFastElements()); |
242 Object* undefined = Heap::undefined_value(); | 303 Object* undefined = Heap::undefined_value(); |
243 | 304 |
244 int len = Smi::cast(array->length())->value(); | 305 int len = Smi::cast(array->length())->value(); |
245 if (len == 0) return undefined; | 306 if (len == 0) return undefined; |
246 | 307 |
247 // Get top element | 308 // Get top element |
248 FixedArray* elms = FixedArray::cast(array->elements()); | 309 FixedArray* elms = FixedArray::cast(array->elements()); |
249 Object* top = elms->get(len - 1); | 310 Object* top = elms->get(len - 1); |
250 | 311 |
251 // Set the length. | 312 // Set the length. |
252 array->set_length(Smi::FromInt(len - 1), SKIP_WRITE_BARRIER); | 313 array->set_length(Smi::FromInt(len - 1), SKIP_WRITE_BARRIER); |
253 | 314 |
254 if (!top->IsTheHole()) { | 315 if (!top->IsTheHole()) { |
255 // Delete the top element. | 316 // Delete the top element. |
256 elms->set_the_hole(len - 1); | 317 elms->set_the_hole(len - 1); |
257 return top; | 318 return top; |
258 } | 319 } |
259 | 320 |
260 // Remember to check the prototype chain. | 321 // Remember to check the prototype chain. |
261 JSFunction* array_function = | 322 JSFunction* array_function = |
262 Top::context()->global_context()->array_function(); | 323 Top::context()->global_context()->array_function(); |
263 JSObject* prototype = JSObject::cast(array_function->prototype()); | 324 JSObject* prototype = JSObject::cast(array_function->prototype()); |
264 top = prototype->GetElement(len - 1); | 325 top = prototype->GetElement(len - 1); |
265 | 326 |
266 return top; | 327 return top; |
267 } | 328 } |
268 BUILTIN_END | |
269 | 329 |
270 | 330 |
271 // ----------------------------------------------------------------------------- | 331 // ----------------------------------------------------------------------------- |
272 // | 332 // |
273 | 333 |
274 | 334 |
275 // Returns the holder JSObject if the function can legally be called | 335 // Returns the holder JSObject if the function can legally be called |
276 // with this receiver. Returns Heap::null_value() if the call is | 336 // with this receiver. Returns Heap::null_value() if the call is |
277 // illegal. Any arguments that don't fit the expected type is | 337 // illegal. Any arguments that don't fit the expected type is |
278 // overwritten with undefined. Arguments that do fit the expected | 338 // overwritten with undefined. Arguments that do fit the expected |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 *arg = current; | 373 *arg = current; |
314 break; | 374 break; |
315 } | 375 } |
316 } | 376 } |
317 if (current == Heap::null_value()) *arg = Heap::undefined_value(); | 377 if (current == Heap::null_value()) *arg = Heap::undefined_value(); |
318 } | 378 } |
319 return holder; | 379 return holder; |
320 } | 380 } |
321 | 381 |
322 | 382 |
323 BUILTIN(HandleApiCall) { | 383 template <bool is_construct> |
| 384 static Object* HandleApiCallHelper( |
| 385 BuiltinArguments<NEEDS_CALLED_FUNCTION> args) { |
| 386 ASSERT(is_construct == CalledAsConstructor()); |
| 387 |
324 HandleScope scope; | 388 HandleScope scope; |
325 bool is_construct = CalledAsConstructor(); | 389 Handle<JSFunction> function = args.called_function(); |
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 | 390 |
331 if (is_construct) { | 391 if (is_construct) { |
332 Handle<FunctionTemplateInfo> desc = | 392 Handle<FunctionTemplateInfo> desc = |
333 Handle<FunctionTemplateInfo>( | 393 Handle<FunctionTemplateInfo>( |
334 FunctionTemplateInfo::cast(function->shared()->function_data())); | 394 FunctionTemplateInfo::cast(function->shared()->function_data())); |
335 bool pending_exception = false; | 395 bool pending_exception = false; |
336 Factory::ConfigureInstance(desc, Handle<JSObject>::cast(receiver), | 396 Factory::ConfigureInstance(desc, Handle<JSObject>::cast(args.receiver()), |
337 &pending_exception); | 397 &pending_exception); |
338 ASSERT(Top::has_pending_exception() == pending_exception); | 398 ASSERT(Top::has_pending_exception() == pending_exception); |
339 if (pending_exception) return Failure::Exception(); | 399 if (pending_exception) return Failure::Exception(); |
340 } | 400 } |
341 | 401 |
342 FunctionTemplateInfo* fun_data = | 402 FunctionTemplateInfo* fun_data = |
343 FunctionTemplateInfo::cast(function->shared()->function_data()); | 403 FunctionTemplateInfo::cast(function->shared()->function_data()); |
344 Object* raw_holder = TypeCheck(args.length(), &args[0], fun_data); | 404 Object* raw_holder = TypeCheck(args.length(), &args[0], fun_data); |
345 | 405 |
346 if (raw_holder->IsNull()) { | 406 if (raw_holder->IsNull()) { |
347 // This function cannot be called with the given receiver. Abort! | 407 // This function cannot be called with the given receiver. Abort! |
348 Handle<Object> obj = | 408 Handle<Object> obj = |
349 Factory::NewTypeError("illegal_invocation", HandleVector(&function, 1)); | 409 Factory::NewTypeError("illegal_invocation", HandleVector(&function, 1)); |
350 return Top::Throw(*obj); | 410 return Top::Throw(*obj); |
351 } | 411 } |
352 | 412 |
353 Object* raw_call_data = fun_data->call_code(); | 413 Object* raw_call_data = fun_data->call_code(); |
354 if (!raw_call_data->IsUndefined()) { | 414 if (!raw_call_data->IsUndefined()) { |
355 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data); | 415 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data); |
356 Object* callback_obj = call_data->callback(); | 416 Object* callback_obj = call_data->callback(); |
357 v8::InvocationCallback callback = | 417 v8::InvocationCallback callback = |
358 v8::ToCData<v8::InvocationCallback>(callback_obj); | 418 v8::ToCData<v8::InvocationCallback>(callback_obj); |
359 Object* data_obj = call_data->data(); | 419 Object* data_obj = call_data->data(); |
360 Object* result; | 420 Object* result; |
361 | 421 |
362 v8::Local<v8::Object> self = | |
363 v8::Utils::ToLocal(Handle<JSObject>::cast(receiver)); | |
364 Handle<Object> data_handle(data_obj); | 422 Handle<Object> data_handle(data_obj); |
365 v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle); | 423 v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle); |
366 ASSERT(raw_holder->IsJSObject()); | 424 ASSERT(raw_holder->IsJSObject()); |
367 v8::Local<v8::Function> callee = v8::Utils::ToLocal(function); | 425 v8::Local<v8::Function> callee = v8::Utils::ToLocal(function); |
368 Handle<JSObject> holder_handle(JSObject::cast(raw_holder)); | 426 Handle<JSObject> holder_handle(JSObject::cast(raw_holder)); |
369 v8::Local<v8::Object> holder = v8::Utils::ToLocal(holder_handle); | 427 v8::Local<v8::Object> holder = v8::Utils::ToLocal(holder_handle); |
370 LOG(ApiObjectAccess("call", JSObject::cast(*receiver))); | 428 LOG(ApiObjectAccess("call", JSObject::cast(*args.receiver()))); |
371 v8::Arguments new_args = v8::ImplementationUtilities::NewArguments( | 429 v8::Arguments new_args = v8::ImplementationUtilities::NewArguments( |
372 data, | 430 data, |
373 holder, | 431 holder, |
374 callee, | 432 callee, |
375 is_construct, | 433 is_construct, |
376 reinterpret_cast<void**>(&args[0] - 1), | 434 reinterpret_cast<void**>(&args[0] - 1), |
377 args.length() - 1); | 435 args.length() - 1); |
378 | 436 |
379 v8::Handle<v8::Value> value; | 437 v8::Handle<v8::Value> value; |
380 { | 438 { |
381 // Leaving JavaScript. | 439 // Leaving JavaScript. |
382 VMState state(EXTERNAL); | 440 VMState state(EXTERNAL); |
383 #ifdef ENABLE_LOGGING_AND_PROFILING | 441 #ifdef ENABLE_LOGGING_AND_PROFILING |
384 state.set_external_callback(v8::ToCData<Address>(callback_obj)); | 442 state.set_external_callback(v8::ToCData<Address>(callback_obj)); |
385 #endif | 443 #endif |
386 value = callback(new_args); | 444 value = callback(new_args); |
387 } | 445 } |
388 if (value.IsEmpty()) { | 446 if (value.IsEmpty()) { |
389 result = Heap::undefined_value(); | 447 result = Heap::undefined_value(); |
390 } else { | 448 } else { |
391 result = *reinterpret_cast<Object**>(*value); | 449 result = *reinterpret_cast<Object**>(*value); |
392 } | 450 } |
393 | 451 |
394 RETURN_IF_SCHEDULED_EXCEPTION(); | 452 RETURN_IF_SCHEDULED_EXCEPTION(); |
395 if (!is_construct || result->IsJSObject()) return result; | 453 if (!is_construct || result->IsJSObject()) return result; |
396 } | 454 } |
397 | 455 |
398 return *receiver; | 456 return *args.receiver(); |
399 } | 457 } |
400 BUILTIN_END | 458 |
| 459 |
| 460 BUILTIN(HandleApiCall) { |
| 461 return HandleApiCallHelper<false>(args); |
| 462 } |
| 463 |
| 464 |
| 465 BUILTIN(HandleApiCallConstruct) { |
| 466 return HandleApiCallHelper<true>(args); |
| 467 } |
401 | 468 |
402 | 469 |
403 // Helper function to handle calls to non-function objects created through the | 470 // 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 | 471 // API. The object can be called as either a constructor (using new) or just as |
405 // a function (without new). | 472 // a function (without new). |
406 static Object* HandleApiCallAsFunctionOrConstructor(bool is_construct_call, | 473 static Object* HandleApiCallAsFunctionOrConstructor( |
407 Arguments args) { | 474 bool is_construct_call, |
| 475 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) { |
408 // Non-functions are never called as constructors. Even if this is an object | 476 // 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. | 477 // called as a constructor the delegate call is not a construct call. |
410 ASSERT(!CalledAsConstructor()); | 478 ASSERT(!CalledAsConstructor()); |
411 | 479 |
412 Handle<Object> receiver = args.at<Object>(0); | 480 Handle<Object> receiver = args.at<Object>(0); |
413 | 481 |
414 // Get the object called. | 482 // Get the object called. |
415 JSObject* obj = JSObject::cast(*receiver); | 483 JSObject* obj = JSObject::cast(*args.receiver()); |
416 | 484 |
417 // Get the invocation callback from the function descriptor that was | 485 // Get the invocation callback from the function descriptor that was |
418 // used to create the called object. | 486 // used to create the called object. |
419 ASSERT(obj->map()->has_instance_call_handler()); | 487 ASSERT(obj->map()->has_instance_call_handler()); |
420 JSFunction* constructor = JSFunction::cast(obj->map()->constructor()); | 488 JSFunction* constructor = JSFunction::cast(obj->map()->constructor()); |
421 Object* template_info = constructor->shared()->function_data(); | 489 Object* template_info = constructor->shared()->function_data(); |
422 Object* handler = | 490 Object* handler = |
423 FunctionTemplateInfo::cast(template_info)->instance_call_handler(); | 491 FunctionTemplateInfo::cast(template_info)->instance_call_handler(); |
424 ASSERT(!handler->IsUndefined()); | 492 ASSERT(!handler->IsUndefined()); |
425 CallHandlerInfo* call_data = CallHandlerInfo::cast(handler); | 493 CallHandlerInfo* call_data = CallHandlerInfo::cast(handler); |
426 Object* callback_obj = call_data->callback(); | 494 Object* callback_obj = call_data->callback(); |
427 v8::InvocationCallback callback = | 495 v8::InvocationCallback callback = |
428 v8::ToCData<v8::InvocationCallback>(callback_obj); | 496 v8::ToCData<v8::InvocationCallback>(callback_obj); |
429 | 497 |
430 // Get the data for the call and perform the callback. | 498 // Get the data for the call and perform the callback. |
431 Object* data_obj = call_data->data(); | 499 Object* data_obj = call_data->data(); |
432 Object* result; | 500 Object* result; |
433 { HandleScope scope; | 501 { HandleScope scope; |
434 v8::Local<v8::Object> self = | 502 v8::Local<v8::Object> self = |
435 v8::Utils::ToLocal(Handle<JSObject>::cast(receiver)); | 503 v8::Utils::ToLocal(Handle<JSObject>::cast(args.receiver())); |
436 Handle<Object> data_handle(data_obj); | 504 Handle<Object> data_handle(data_obj); |
437 v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle); | 505 v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle); |
438 Handle<JSFunction> callee_handle(constructor); | 506 Handle<JSFunction> callee_handle(constructor); |
439 v8::Local<v8::Function> callee = v8::Utils::ToLocal(callee_handle); | 507 v8::Local<v8::Function> callee = v8::Utils::ToLocal(callee_handle); |
440 LOG(ApiObjectAccess("call non-function", JSObject::cast(*receiver))); | 508 LOG(ApiObjectAccess("call non-function", JSObject::cast(*args.receiver()))); |
441 v8::Arguments new_args = v8::ImplementationUtilities::NewArguments( | 509 v8::Arguments new_args = v8::ImplementationUtilities::NewArguments( |
442 data, | 510 data, |
443 self, | 511 self, |
444 callee, | 512 callee, |
445 is_construct_call, | 513 is_construct_call, |
446 reinterpret_cast<void**>(&args[0] - 1), | 514 reinterpret_cast<void**>(&args[0] - 1), |
447 args.length() - 1); | 515 args.length() - 1); |
448 v8::Handle<v8::Value> value; | 516 v8::Handle<v8::Value> value; |
449 { | 517 { |
450 // Leaving JavaScript. | 518 // Leaving JavaScript. |
(...skipping 13 matching lines...) Expand all Loading... |
464 RETURN_IF_SCHEDULED_EXCEPTION(); | 532 RETURN_IF_SCHEDULED_EXCEPTION(); |
465 return result; | 533 return result; |
466 } | 534 } |
467 | 535 |
468 | 536 |
469 // Handle calls to non-function objects created through the API. This delegate | 537 // Handle calls to non-function objects created through the API. This delegate |
470 // function is used when the call is a normal function call. | 538 // function is used when the call is a normal function call. |
471 BUILTIN(HandleApiCallAsFunction) { | 539 BUILTIN(HandleApiCallAsFunction) { |
472 return HandleApiCallAsFunctionOrConstructor(false, args); | 540 return HandleApiCallAsFunctionOrConstructor(false, args); |
473 } | 541 } |
474 BUILTIN_END | |
475 | 542 |
476 | 543 |
477 // Handle calls to non-function objects created through the API. This delegate | 544 // Handle calls to non-function objects created through the API. This delegate |
478 // function is used when the call is a construct call. | 545 // function is used when the call is a construct call. |
479 BUILTIN(HandleApiCallAsConstructor) { | 546 BUILTIN(HandleApiCallAsConstructor) { |
480 return HandleApiCallAsFunctionOrConstructor(true, args); | 547 return HandleApiCallAsFunctionOrConstructor(true, args); |
481 } | 548 } |
482 BUILTIN_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. | |
488 Object* Builtins::builtin_passed_function; | |
489 | |
490 | 549 |
491 | 550 |
492 static void Generate_LoadIC_ArrayLength(MacroAssembler* masm) { | 551 static void Generate_LoadIC_ArrayLength(MacroAssembler* masm) { |
493 LoadIC::GenerateArrayLength(masm); | 552 LoadIC::GenerateArrayLength(masm); |
494 } | 553 } |
495 | 554 |
496 | 555 |
497 static void Generate_LoadIC_StringLength(MacroAssembler* masm) { | 556 static void Generate_LoadIC_StringLength(MacroAssembler* masm) { |
498 LoadIC::GenerateStringLength(masm); | 557 LoadIC::GenerateStringLength(masm); |
499 } | 558 } |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
701 | 760 |
702 | 761 |
703 static void Generate_StubNoRegisters_DebugBreak(MacroAssembler* masm) { | 762 static void Generate_StubNoRegisters_DebugBreak(MacroAssembler* masm) { |
704 Debug::GenerateStubNoRegistersDebugBreak(masm); | 763 Debug::GenerateStubNoRegistersDebugBreak(masm); |
705 } | 764 } |
706 #endif | 765 #endif |
707 | 766 |
708 Object* Builtins::builtins_[builtin_count] = { NULL, }; | 767 Object* Builtins::builtins_[builtin_count] = { NULL, }; |
709 const char* Builtins::names_[builtin_count] = { NULL, }; | 768 const char* Builtins::names_[builtin_count] = { NULL, }; |
710 | 769 |
711 #define DEF_ENUM_C(name) FUNCTION_ADDR(Builtin_##name), | 770 #define DEF_ENUM_C(name, ignore) FUNCTION_ADDR(Builtin_##name), |
712 Address Builtins::c_functions_[cfunction_count] = { | 771 Address Builtins::c_functions_[cfunction_count] = { |
713 BUILTIN_LIST_C(DEF_ENUM_C) | 772 BUILTIN_LIST_C(DEF_ENUM_C) |
714 }; | 773 }; |
715 #undef DEF_ENUM_C | 774 #undef DEF_ENUM_C |
716 | 775 |
717 #define DEF_JS_NAME(name, ignore) #name, | 776 #define DEF_JS_NAME(name, ignore) #name, |
718 #define DEF_JS_ARGC(ignore, argc) argc, | 777 #define DEF_JS_ARGC(ignore, argc) argc, |
719 const char* Builtins::javascript_names_[id_count] = { | 778 const char* Builtins::javascript_names_[id_count] = { |
720 BUILTINS_LIST_JS(DEF_JS_NAME) | 779 BUILTINS_LIST_JS(DEF_JS_NAME) |
721 }; | 780 }; |
(...skipping 10 matching lines...) Expand all Loading... |
732 | 791 |
733 // Create a scope for the handles in the builtins. | 792 // Create a scope for the handles in the builtins. |
734 HandleScope scope; | 793 HandleScope scope; |
735 | 794 |
736 struct BuiltinDesc { | 795 struct BuiltinDesc { |
737 byte* generator; | 796 byte* generator; |
738 byte* c_code; | 797 byte* c_code; |
739 const char* s_name; // name is only used for generating log information. | 798 const char* s_name; // name is only used for generating log information. |
740 int name; | 799 int name; |
741 Code::Flags flags; | 800 Code::Flags flags; |
| 801 BuiltinExtraArguments extra_args; |
742 }; | 802 }; |
743 | 803 |
744 #define DEF_FUNCTION_PTR_C(name) \ | 804 #define DEF_FUNCTION_PTR_C(name, extra_args) \ |
745 { FUNCTION_ADDR(Generate_Adaptor), \ | 805 { FUNCTION_ADDR(Generate_Adaptor), \ |
746 FUNCTION_ADDR(Builtin_##name), \ | 806 FUNCTION_ADDR(Builtin_##name), \ |
747 #name, \ | 807 #name, \ |
748 c_##name, \ | 808 c_##name, \ |
749 Code::ComputeFlags(Code::BUILTIN) \ | 809 Code::ComputeFlags(Code::BUILTIN), \ |
| 810 extra_args \ |
750 }, | 811 }, |
751 | 812 |
752 #define DEF_FUNCTION_PTR_A(name, kind, state) \ | 813 #define DEF_FUNCTION_PTR_A(name, kind, state) \ |
753 { FUNCTION_ADDR(Generate_##name), \ | 814 { FUNCTION_ADDR(Generate_##name), \ |
754 NULL, \ | 815 NULL, \ |
755 #name, \ | 816 #name, \ |
756 name, \ | 817 name, \ |
757 Code::ComputeFlags(Code::kind, NOT_IN_LOOP, state) \ | 818 Code::ComputeFlags(Code::kind, NOT_IN_LOOP, state), \ |
| 819 NO_EXTRA_ARGUMENTS \ |
758 }, | 820 }, |
759 | 821 |
760 // Define array of pointers to generators and C builtin functions. | 822 // Define array of pointers to generators and C builtin functions. |
761 static BuiltinDesc functions[] = { | 823 static BuiltinDesc functions[] = { |
762 BUILTIN_LIST_C(DEF_FUNCTION_PTR_C) | 824 BUILTIN_LIST_C(DEF_FUNCTION_PTR_C) |
763 BUILTIN_LIST_A(DEF_FUNCTION_PTR_A) | 825 BUILTIN_LIST_A(DEF_FUNCTION_PTR_A) |
764 BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A) | 826 BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A) |
765 // Terminator: | 827 // Terminator: |
766 { NULL, NULL, NULL, builtin_count, static_cast<Code::Flags>(0) } | 828 { NULL, NULL, NULL, builtin_count, static_cast<Code::Flags>(0), |
| 829 NO_EXTRA_ARGUMENTS } |
767 }; | 830 }; |
768 | 831 |
769 #undef DEF_FUNCTION_PTR_C | 832 #undef DEF_FUNCTION_PTR_C |
770 #undef DEF_FUNCTION_PTR_A | 833 #undef DEF_FUNCTION_PTR_A |
771 | 834 |
772 // For now we generate builtin adaptor code into a stack-allocated | 835 // For now we generate builtin adaptor code into a stack-allocated |
773 // buffer, before copying it into individual code objects. | 836 // buffer, before copying it into individual code objects. |
774 byte buffer[4*KB]; | 837 byte buffer[4*KB]; |
775 | 838 |
776 // Traverse the list of builtins and generate an adaptor in a | 839 // Traverse the list of builtins and generate an adaptor in a |
777 // separate code object for each one. | 840 // separate code object for each one. |
778 for (int i = 0; i < builtin_count; i++) { | 841 for (int i = 0; i < builtin_count; i++) { |
779 if (create_heap_objects) { | 842 if (create_heap_objects) { |
780 MacroAssembler masm(buffer, sizeof buffer); | 843 MacroAssembler masm(buffer, sizeof buffer); |
781 // Generate the code/adaptor. | 844 // Generate the code/adaptor. |
782 typedef void (*Generator)(MacroAssembler*, int); | 845 typedef void (*Generator)(MacroAssembler*, int, BuiltinExtraArguments); |
783 Generator g = FUNCTION_CAST<Generator>(functions[i].generator); | 846 Generator g = FUNCTION_CAST<Generator>(functions[i].generator); |
784 // We pass all arguments to the generator, but it may not use all of | 847 // We pass all arguments to the generator, but it may not use all of |
785 // them. This works because the first arguments are on top of the | 848 // them. This works because the first arguments are on top of the |
786 // stack. | 849 // stack. |
787 g(&masm, functions[i].name); | 850 g(&masm, functions[i].name, functions[i].extra_args); |
788 // Move the code into the object heap. | 851 // Move the code into the object heap. |
789 CodeDesc desc; | 852 CodeDesc desc; |
790 masm.GetCode(&desc); | 853 masm.GetCode(&desc); |
791 Code::Flags flags = functions[i].flags; | 854 Code::Flags flags = functions[i].flags; |
792 Object* code; | 855 Object* code; |
793 { | 856 { |
794 // During startup it's OK to always allocate and defer GC to later. | 857 // During startup it's OK to always allocate and defer GC to later. |
795 // This simplifies things because we don't need to retry. | 858 // This simplifies things because we don't need to retry. |
796 AlwaysAllocateScope __scope__; | 859 AlwaysAllocateScope __scope__; |
797 code = Heap::CreateCode(desc, NULL, flags, masm.CodeObject()); | 860 code = Heap::CreateCode(desc, NULL, flags, masm.CodeObject()); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
842 if (entry->contains(pc)) { | 905 if (entry->contains(pc)) { |
843 return names_[i]; | 906 return names_[i]; |
844 } | 907 } |
845 } | 908 } |
846 } | 909 } |
847 return NULL; | 910 return NULL; |
848 } | 911 } |
849 | 912 |
850 | 913 |
851 } } // namespace v8::internal | 914 } } // namespace v8::internal |
OLD | NEW |