Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(711)

Side by Side Diff: src/builtins.cc

Issue 536065: Optimized calling of C++ builtins (and HandleApiCall (Closed)
Patch Set: Created 10 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/builtins.h ('k') | src/factory.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/builtins.h ('k') | src/factory.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698