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

Side by Side Diff: src/builtins.cc

Issue 3079: Remove the old builtins framework with the huge, nasty (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 12 years, 3 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 | Annotate | Revision Log
« no previous file with comments | « src/builtins.h ('k') | src/builtins-arm.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 22 matching lines...) Expand all
33 #include "ic-inl.h" 33 #include "ic-inl.h"
34 34
35 namespace v8 { namespace internal { 35 namespace v8 { namespace internal {
36 36
37 // ---------------------------------------------------------------------------- 37 // ----------------------------------------------------------------------------
38 // Support macros for defining builtins in C. 38 // Support macros for defining builtins in C.
39 // ---------------------------------------------------------------------------- 39 // ----------------------------------------------------------------------------
40 // 40 //
41 // A builtin function is defined by writing: 41 // A builtin function is defined by writing:
42 // 42 //
43 // BUILTIN_<n>(name, ...) 43 // BUILTIN(name) {
44 // {
45 // ... 44 // ...
46 // } 45 // }
47 // BUILTIN_END 46 // BUILTIN_END
48 // 47 //
49 // where <n> is the number of arguments (not counting the receiver). The 48 // In the body of the builtin function, the variable 'receiver' is visible.
50 // names of the arguments must be listed after the name in the declaration. 49 // The arguments can be accessed through:
51 // In the body of the builtin function, the variables 'env' and 'receiver'
52 // are visible. The arguments can be accessed through:
53 // 50 //
54 // BUILTIN_ARG(0): Receiver (also available as 'receiver') 51 // BUILTIN_ARG(0): Receiver (also available as 'receiver')
55 // BUILTIN_ARG(1): First argument 52 // BUILTIN_ARG(1): First argument
56 // ... 53 // ...
57 // BUILTIN_ARG(n): Last argument 54 // BUILTIN_ARG(n): Last argument
58 // 55 //
59 // and they evaluate to undefined values if too few arguments were 56 // and they evaluate to undefined values if too few arguments were
60 // passed to the builtin function invocation. 57 // passed to the builtin function invocation.
61 // 58 //
62 // __argc__ is the number of arguments including the receiver. 59 // __argc__ is the number of arguments including the receiver.
63 // ---------------------------------------------------------------------------- 60 // ----------------------------------------------------------------------------
64 61
65 62
66 // TODO(1238487): This is not okay. We need to get rid of this macro 63 // TODO(1238487): We should consider passing whether or not the
67 // and start calling the builtins in a more direct way. Looking at the 64 // builtin was invoked as a constructor as part of the
68 // stack frames for all builtin invocations comes with a pretty 65 // arguments. Maybe we also want to pass the called function?
69 // significant performance penalty.
70 #define BUILTIN(name) \ 66 #define BUILTIN(name) \
71 static Object* Builtin_##name(int __argc__, \
72 Object** __argv__) { \
73 Handle<Object> receiver(&__argv__[0]); \
74 bool is_construct = false; \
75 USE(__argc__); \
76 USE(__argv__); \
77 { StackFrameIterator it; \
78 ASSERT(it.frame()->is_exit()); \
79 it.Advance(); \
80 StackFrame::Type type = it.frame()->type(); \
81 if (type == StackFrame::INTERNAL) { \
82 InternalFrame* frame = InternalFrame::cast(it.frame()); \
83 is_construct = frame->is_construct_trampoline(); \
84 } else if (type == StackFrame::ARGUMENTS_ADAPTOR) { \
85 ArgumentsAdaptorFrame* frame = \
86 ArgumentsAdaptorFrame::cast(it.frame()); \
87 /* __argc__ includes the receiver. */ \
88 __argc__ = frame->GetProvidedParametersCount() + 1; \
89 __argv__ = reinterpret_cast<Object**>(frame->pp()) - 1; \
90 it.Advance(); \
91 is_construct = \
92 it.frame()->is_internal() && \
93 InternalFrame::cast(it.frame())->is_construct_trampoline(); \
94 } \
95 }
96
97
98 // We're transitioning to a much simpler builtins framework where all
99 // builtins are called *without* arguments adaption. For now, only a
100 // few of the builtins have been rewritten to support this and they
101 // all use the NEW_BUILTIN macro instead of plain old BUILTIN.
102 #define NEW_BUILTIN(name) \
103 static Object* Builtin_##name(int __argc__, Object** __argv__) { \ 67 static Object* Builtin_##name(int __argc__, Object** __argv__) { \
104 Handle<Object> receiver(&__argv__[0]); 68 Handle<Object> receiver(&__argv__[0]);
105 69
106 70
107 // Use an inline function to avoid evaluating the index (n) more than 71 // Use an inline function to avoid evaluating the index (n) more than
108 // once in the BUILTIN_ARG macro. 72 // once in the BUILTIN_ARG macro.
109 static inline Object* __builtin_arg__(int n, int argc, Object** argv) { 73 static inline Object* __builtin_arg__(int n, int argc, Object** argv) {
110 ASSERT(n >= 0); 74 ASSERT(n >= 0);
111 return (argc > n) ? argv[-n] : Heap::undefined_value(); 75 return (argc > n) ? argv[-n] : Heap::undefined_value();
112 } 76 }
113 77
114 78
115 // NOTE: Argument 0 is the receiver. The first 'real' argument is 79 // NOTE: Argument 0 is the receiver. The first 'real' argument is
116 // argument 1 - BUILTIN_ARG(1). 80 // argument 1 - BUILTIN_ARG(1).
117 #define BUILTIN_ARG(n) (__builtin_arg__(n, __argc__, __argv__)) 81 #define BUILTIN_ARG(n) (__builtin_arg__(n, __argc__, __argv__))
118 82
119 83
120 #define BUILTIN_END \ 84 #define BUILTIN_END \
121 return Heap::undefined_value(); \ 85 return Heap::undefined_value(); \
122 } 86 }
123 87
124 88
89 // TODO(1238487): Get rid of this function that determines if the
90 // builtin is called as a constructor. This may be a somewhat slow
91 // operation due to the stack frame iteration.
92 static inline bool CalledAsConstructor() {
93 StackFrameIterator it;
94 ASSERT(it.frame()->is_exit());
95 it.Advance();
96 StackFrame* frame = it.frame();
97 return frame->is_internal() &&
98 InternalFrame::cast(frame)->is_construct_trampoline();
99 }
100
101
125 // ---------------------------------------------------------------------------- 102 // ----------------------------------------------------------------------------
126 103
127 104
128 int Builtins::construct_call_pc_offset_ = 0; 105 int Builtins::construct_call_pc_offset_ = 0;
129 int Builtins::arguments_adaptor_call_pc_offset_ = 0; 106 int Builtins::arguments_adaptor_call_pc_offset_ = 0;
130 107
131 108
132 // Check if the builtin was called in a 'new' call. 109 // Check if the builtin was called in a 'new' call.
133 bool Builtins::IsConstructCall(Address pc) { 110 bool Builtins::IsConstructCall(Address pc) {
134 ASSERT(construct_call_pc_offset_ > 0); 111 ASSERT(construct_call_pc_offset_ > 0);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 BUILTIN_END 149 BUILTIN_END
173 150
174 151
175 BUILTIN(EmptyFunction) { 152 BUILTIN(EmptyFunction) {
176 } 153 }
177 BUILTIN_END 154 BUILTIN_END
178 155
179 156
180 BUILTIN(ArrayCode) { 157 BUILTIN(ArrayCode) {
181 JSArray* array; 158 JSArray* array;
182 if (is_construct) { 159 if (CalledAsConstructor()) {
183 array = JSArray::cast(*receiver); 160 array = JSArray::cast(*receiver);
184 } else { 161 } else {
185 // Allocate the JS Array 162 // Allocate the JS Array
186 JSFunction* constructor = 163 JSFunction* constructor =
187 Top::context()->global_context()->array_function(); 164 Top::context()->global_context()->array_function();
188 Object* obj = Heap::AllocateJSObject(constructor); 165 Object* obj = Heap::AllocateJSObject(constructor);
189 if (obj->IsFailure()) return obj; 166 if (obj->IsFailure()) return obj;
190 array = JSArray::cast(obj); 167 array = JSArray::cast(obj);
191 } 168 }
192 169
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 205
229 // Set length and elements on the array. 206 // Set length and elements on the array.
230 array->set_elements(FixedArray::cast(obj)); 207 array->set_elements(FixedArray::cast(obj));
231 array->set_length(len); 208 array->set_length(len);
232 209
233 return array; 210 return array;
234 } 211 }
235 BUILTIN_END 212 BUILTIN_END
236 213
237 214
238 NEW_BUILTIN(ArrayPush) { 215 BUILTIN(ArrayPush) {
239 JSArray* array = JSArray::cast(*receiver); 216 JSArray* array = JSArray::cast(*receiver);
240 ASSERT(array->HasFastElements()); 217 ASSERT(array->HasFastElements());
241 218
242 // Make sure we have space for the elements. 219 // Make sure we have space for the elements.
243 int len = Smi::cast(array->length())->value(); 220 int len = Smi::cast(array->length())->value();
244 221
245 // Set new length. 222 // Set new length.
246 int new_length = len + __argc__ - 1; 223 int new_length = len + __argc__ - 1;
247 FixedArray* elms = FixedArray::cast(array->elements()); 224 FixedArray* elms = FixedArray::cast(array->elements());
248 225
(...skipping 18 matching lines...) Expand all
267 // Set the new backing storage. 244 // Set the new backing storage.
268 array->set_elements(new_elms); 245 array->set_elements(new_elms);
269 } 246 }
270 // Set the length. 247 // Set the length.
271 array->set_length(Smi::FromInt(new_length)); 248 array->set_length(Smi::FromInt(new_length));
272 return array->length(); 249 return array->length();
273 } 250 }
274 BUILTIN_END 251 BUILTIN_END
275 252
276 253
277 NEW_BUILTIN(ArrayPop) { 254 BUILTIN(ArrayPop) {
278 JSArray* array = JSArray::cast(*receiver); 255 JSArray* array = JSArray::cast(*receiver);
279 ASSERT(array->HasFastElements()); 256 ASSERT(array->HasFastElements());
280 Object* undefined = Heap::undefined_value(); 257 Object* undefined = Heap::undefined_value();
281 258
282 int len = Smi::cast(array->length())->value(); 259 int len = Smi::cast(array->length())->value();
283 if (len == 0) return undefined; 260 if (len == 0) return undefined;
284 261
285 // Get top element 262 // Get top element
286 FixedArray* elms = FixedArray::cast(array->elements()); 263 FixedArray* elms = FixedArray::cast(array->elements());
287 Object* top = elms->get(len - 1); 264 Object* top = elms->get(len - 1);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
354 } 331 }
355 } 332 }
356 if (current == Heap::null_value()) *arg = Heap::undefined_value(); 333 if (current == Heap::null_value()) *arg = Heap::undefined_value();
357 } 334 }
358 return holder; 335 return holder;
359 } 336 }
360 337
361 338
362 BUILTIN(HandleApiCall) { 339 BUILTIN(HandleApiCall) {
363 HandleScope scope; 340 HandleScope scope;
341 bool is_construct = CalledAsConstructor();
364 342
365 // TODO(1238487): This is not nice. We need to get rid of this 343 // TODO(1238487): This is not nice. We need to get rid of this
366 // kludgy behavior and start handling API calls in a more direct 344 // kludgy behavior and start handling API calls in a more direct
367 // way - maybe compile specialized stubs lazily?. 345 // way - maybe compile specialized stubs lazily?.
368 Handle<JSFunction> function = 346 Handle<JSFunction> function =
369 Handle<JSFunction>(JSFunction::cast(Builtins::builtin_passed_function)); 347 Handle<JSFunction>(JSFunction::cast(Builtins::builtin_passed_function));
370 348
371 if (is_construct) { 349 if (is_construct) {
372 Handle<FunctionTemplateInfo> desc = 350 Handle<FunctionTemplateInfo> desc =
373 Handle<FunctionTemplateInfo>( 351 Handle<FunctionTemplateInfo>(
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
434 412
435 return *receiver; 413 return *receiver;
436 } 414 }
437 BUILTIN_END 415 BUILTIN_END
438 416
439 417
440 // Handle calls to non-function objects created through the API that 418 // Handle calls to non-function objects created through the API that
441 // support calls. 419 // support calls.
442 BUILTIN(HandleApiCallAsFunction) { 420 BUILTIN(HandleApiCallAsFunction) {
443 // Non-functions are never called as constructors. 421 // Non-functions are never called as constructors.
444 ASSERT(!is_construct); 422 ASSERT(!CalledAsConstructor());
445 423
446 // Get the object called. 424 // Get the object called.
447 JSObject* obj = JSObject::cast(*receiver); 425 JSObject* obj = JSObject::cast(*receiver);
448 426
449 // Get the invocation callback from the function descriptor that was 427 // Get the invocation callback from the function descriptor that was
450 // used to create the called object. 428 // used to create the called object.
451 ASSERT(obj->map()->has_instance_call_handler()); 429 ASSERT(obj->map()->has_instance_call_handler());
452 JSFunction* constructor = JSFunction::cast(obj->map()->constructor()); 430 JSFunction* constructor = JSFunction::cast(obj->map()->constructor());
453 Object* template_info = constructor->shared()->function_data(); 431 Object* template_info = constructor->shared()->function_data();
454 Object* handler = 432 Object* handler =
(...skipping 12 matching lines...) Expand all
467 v8::Utils::ToLocal(Handle<JSObject>::cast(receiver)); 445 v8::Utils::ToLocal(Handle<JSObject>::cast(receiver));
468 Handle<Object> data_handle(data_obj); 446 Handle<Object> data_handle(data_obj);
469 v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle); 447 v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle);
470 Handle<JSFunction> callee_handle(constructor); 448 Handle<JSFunction> callee_handle(constructor);
471 v8::Local<v8::Function> callee = v8::Utils::ToLocal(callee_handle); 449 v8::Local<v8::Function> callee = v8::Utils::ToLocal(callee_handle);
472 LOG(ApiObjectAccess("call non-function", JSObject::cast(*receiver))); 450 LOG(ApiObjectAccess("call non-function", JSObject::cast(*receiver)));
473 v8::Arguments args = v8::ImplementationUtilities::NewArguments( 451 v8::Arguments args = v8::ImplementationUtilities::NewArguments(
474 data, 452 data,
475 self, 453 self,
476 callee, 454 callee,
477 is_construct, 455 false,
478 reinterpret_cast<void**>(__argv__ - 1), 456 reinterpret_cast<void**>(__argv__ - 1),
479 __argc__ - 1); 457 __argc__ - 1);
480 v8::Handle<v8::Value> value; 458 v8::Handle<v8::Value> value;
481 { 459 {
482 // Leaving JavaScript. 460 // Leaving JavaScript.
483 VMState state(OTHER); 461 VMState state(OTHER);
484 value = callback(args); 462 value = callback(args);
485 } 463 }
486 if (value.IsEmpty()) { 464 if (value.IsEmpty()) {
487 result = Heap::undefined_value(); 465 result = Heap::undefined_value();
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 577
600 578
601 static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) { 579 static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) {
602 KeyedStoreIC::GenerateInitialize(masm); 580 KeyedStoreIC::GenerateInitialize(masm);
603 } 581 }
604 582
605 583
606 Object* Builtins::builtins_[builtin_count] = { NULL, }; 584 Object* Builtins::builtins_[builtin_count] = { NULL, };
607 const char* Builtins::names_[builtin_count] = { NULL, }; 585 const char* Builtins::names_[builtin_count] = { NULL, };
608 586
609 #define DEF_ENUM_C(name, ignore) FUNCTION_ADDR(Builtin_##name), 587 #define DEF_ENUM_C(name) FUNCTION_ADDR(Builtin_##name),
610 Address Builtins::c_functions_[cfunction_count] = { 588 Address Builtins::c_functions_[cfunction_count] = {
611 BUILTIN_LIST_C(DEF_ENUM_C) 589 BUILTIN_LIST_C(DEF_ENUM_C)
612 }; 590 };
613 #undef DEF_ENUM_C 591 #undef DEF_ENUM_C
614 592
615 #define DEF_JS_NAME(name, ignore) #name, 593 #define DEF_JS_NAME(name, ignore) #name,
616 #define DEF_JS_ARGC(ignore, argc) argc, 594 #define DEF_JS_ARGC(ignore, argc) argc,
617 const char* Builtins::javascript_names_[id_count] = { 595 const char* Builtins::javascript_names_[id_count] = {
618 BUILTINS_LIST_JS(DEF_JS_NAME) 596 BUILTINS_LIST_JS(DEF_JS_NAME)
619 }; 597 };
(...skipping 10 matching lines...) Expand all
630 608
631 // Create a scope for the handles in the builtins. 609 // Create a scope for the handles in the builtins.
632 HandleScope scope; 610 HandleScope scope;
633 611
634 struct BuiltinDesc { 612 struct BuiltinDesc {
635 byte* generator; 613 byte* generator;
636 byte* c_code; 614 byte* c_code;
637 const char* s_name; // name is only used for generating log information. 615 const char* s_name; // name is only used for generating log information.
638 int name; 616 int name;
639 Code::Flags flags; 617 Code::Flags flags;
640 int argc;
641 }; 618 };
642 619
643 #define DEF_FUNCTION_PTR_C(name, argc) \ 620 #define DEF_FUNCTION_PTR_C(name) \
644 { FUNCTION_ADDR(Generate_Adaptor), \ 621 { FUNCTION_ADDR(Generate_Adaptor), \
645 FUNCTION_ADDR(Builtin_##name), \ 622 FUNCTION_ADDR(Builtin_##name), \
646 #name, \ 623 #name, \
647 c_##name, \ 624 c_##name, \
648 Code::ComputeFlags(Code::BUILTIN), \ 625 Code::ComputeFlags(Code::BUILTIN) \
649 argc \
650 }, 626 },
651 627
652 #define DEF_FUNCTION_PTR_A(name, kind, state) \ 628 #define DEF_FUNCTION_PTR_A(name, kind, state) \
653 { FUNCTION_ADDR(Generate_##name), \ 629 { FUNCTION_ADDR(Generate_##name), \
654 NULL, \ 630 NULL, \
655 #name, \ 631 #name, \
656 name, \ 632 name, \
657 Code::ComputeFlags(Code::kind, state), \ 633 Code::ComputeFlags(Code::kind, state) \
658 -1 \
659 }, 634 },
660 635
661 // Define array of pointers to generators and C builtin functions. 636 // Define array of pointers to generators and C builtin functions.
662 static BuiltinDesc functions[] = { 637 static BuiltinDesc functions[] = {
663 BUILTIN_LIST_C(DEF_FUNCTION_PTR_C) 638 BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
664 BUILTIN_LIST_A(DEF_FUNCTION_PTR_A) 639 BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
665 // Terminator: 640 // Terminator:
666 { NULL, NULL, NULL, builtin_count, static_cast<Code::Flags>(0), -1} 641 { NULL, NULL, NULL, builtin_count, static_cast<Code::Flags>(0) }
667 }; 642 };
668 643
669 #undef DEF_FUNCTION_PTR_C 644 #undef DEF_FUNCTION_PTR_C
670 #undef DEF_FUNCTION_PTR_A 645 #undef DEF_FUNCTION_PTR_A
671 646
672 // For now we generate builtin adaptor code into a stack-allocated 647 // For now we generate builtin adaptor code into a stack-allocated
673 // buffer, before copying it into individual code objects. 648 // buffer, before copying it into individual code objects.
674 byte buffer[4*KB]; 649 byte buffer[4*KB];
675 650
676 // Traverse the list of builtins and generate an adaptor in a 651 // Traverse the list of builtins and generate an adaptor in a
677 // separate code object for each one. 652 // separate code object for each one.
678 for (int i = 0; i < builtin_count; i++) { 653 for (int i = 0; i < builtin_count; i++) {
679 if (create_heap_objects) { 654 if (create_heap_objects) {
680 MacroAssembler masm(buffer, sizeof buffer); 655 MacroAssembler masm(buffer, sizeof buffer);
681 // Generate the code/adaptor. 656 // Generate the code/adaptor.
682 typedef void (*Generator)(MacroAssembler*, int, int); 657 typedef void (*Generator)(MacroAssembler*, int);
683 Generator g = FUNCTION_CAST<Generator>(functions[i].generator); 658 Generator g = FUNCTION_CAST<Generator>(functions[i].generator);
684 // We pass all arguments to the generator, but it may not use all of 659 // We pass all arguments to the generator, but it may not use all of
685 // them. This works because the first arguments are on top of the 660 // them. This works because the first arguments are on top of the
686 // stack. 661 // stack.
687 g(&masm, functions[i].argc, functions[i].name); 662 g(&masm, functions[i].name);
688 // Move the code into the object heap. 663 // Move the code into the object heap.
689 CodeDesc desc; 664 CodeDesc desc;
690 masm.GetCode(&desc); 665 masm.GetCode(&desc);
691 Code::Flags flags = functions[i].flags; 666 Code::Flags flags = functions[i].flags;
692 Object* code = Heap::CreateCode(desc, NULL, flags); 667 Object* code = Heap::CreateCode(desc, NULL, flags);
693 if (code->IsRetryAfterGC()) { 668 if (code->IsRetryAfterGC()) {
694 CHECK(Heap::CollectGarbage(Failure::cast(code)->requested(), 669 CHECK(Heap::CollectGarbage(Failure::cast(code)->requested(),
695 Failure::cast(code)->allocation_space())); 670 Failure::cast(code)->allocation_space()));
696 code = Heap::CreateCode(desc, NULL, flags); 671 code = Heap::CreateCode(desc, NULL, flags);
697 } 672 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
737 if (entry->contains(pc)) { 712 if (entry->contains(pc)) {
738 return names_[i]; 713 return names_[i];
739 } 714 }
740 } 715 }
741 } 716 }
742 return NULL; 717 return NULL;
743 } 718 }
744 719
745 720
746 } } // namespace v8::internal 721 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/builtins.h ('k') | src/builtins-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698