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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 // passed to the builtin function invocation. | 60 // passed to the builtin function invocation. |
61 // | 61 // |
62 // __argc__ is the number of arguments including the receiver. | 62 // __argc__ is the number of arguments including the receiver. |
63 // ---------------------------------------------------------------------------- | 63 // ---------------------------------------------------------------------------- |
64 | 64 |
65 | 65 |
66 // TODO(1238487): This is not okay. We need to get rid of this macro | 66 // TODO(1238487): This is not okay. We need to get rid of this macro |
67 // and start calling the builtins in a more direct way. Looking at the | 67 // and start calling the builtins in a more direct way. Looking at the |
68 // stack frames for all builtin invocations comes with a pretty | 68 // stack frames for all builtin invocations comes with a pretty |
69 // significant performance penalty. | 69 // significant performance penalty. |
70 #define BUILTIN_0(name) \ | 70 #define BUILTIN(name) \ |
71 static Object* Builtin_##name(int __argc__, \ | 71 static Object* Builtin_##name(int __argc__, \ |
72 Object** __argv__) { \ | 72 Object** __argv__) { \ |
73 Handle<Object> receiver(&__argv__[0]); \ | 73 Handle<Object> receiver(&__argv__[0]); \ |
74 bool is_construct = false; \ | 74 bool is_construct = false; \ |
75 USE(__argc__); \ | 75 USE(__argc__); \ |
76 USE(__argv__); \ | 76 USE(__argv__); \ |
77 { StackFrameIterator it; \ | 77 { StackFrameIterator it; \ |
78 ASSERT(it.frame()->is_exit()); \ | 78 ASSERT(it.frame()->is_exit()); \ |
79 it.Advance(); \ | 79 it.Advance(); \ |
80 StackFrame::Type type = it.frame()->type(); \ | 80 StackFrame::Type type = it.frame()->type(); \ |
81 if (type == StackFrame::INTERNAL) { \ | 81 if (type == StackFrame::INTERNAL) { \ |
82 InternalFrame* frame = InternalFrame::cast(it.frame()); \ | 82 InternalFrame* frame = InternalFrame::cast(it.frame()); \ |
83 is_construct = frame->is_construct_trampoline(); \ | 83 is_construct = frame->is_construct_trampoline(); \ |
84 } else if (type == StackFrame::ARGUMENTS_ADAPTOR) { \ | 84 } else if (type == StackFrame::ARGUMENTS_ADAPTOR) { \ |
85 ArgumentsAdaptorFrame* frame = \ | 85 ArgumentsAdaptorFrame* frame = \ |
86 ArgumentsAdaptorFrame::cast(it.frame()); \ | 86 ArgumentsAdaptorFrame::cast(it.frame()); \ |
87 /* __argc__ includes the receiver. */ \ | 87 /* __argc__ includes the receiver. */ \ |
88 __argc__ = frame->GetProvidedParametersCount() + 1; \ | 88 __argc__ = frame->GetProvidedParametersCount() + 1; \ |
89 __argv__ = reinterpret_cast<Object**>(frame->pp()) - 1; \ | 89 __argv__ = reinterpret_cast<Object**>(frame->pp()) - 1; \ |
90 it.Advance(); \ | 90 it.Advance(); \ |
91 is_construct = \ | 91 is_construct = \ |
92 it.frame()->is_internal() && \ | 92 it.frame()->is_internal() && \ |
93 InternalFrame::cast(it.frame())->is_construct_trampoline(); \ | 93 InternalFrame::cast(it.frame())->is_construct_trampoline(); \ |
94 } \ | 94 } \ |
95 } | 95 } |
96 | 96 |
97 | 97 |
98 #define BUILTIN_1(name, a0) \ | 98 // We're transitioning to a much simpler builtins framework where all |
99 BUILTIN_0(name) \ | 99 // builtins are called *without* arguments adaption. For now, only a |
100 Object* a0 = BUILTIN_ARG(1); | 100 // few of the builtins have been rewritten to support this and they |
101 | 101 // all use the NEW_BUILTIN macro instead of plain old BUILTIN. |
102 | 102 #define NEW_BUILTIN(name) \ |
103 #define BUILTIN_2(name, a0, a1) \ | 103 static Object* Builtin_##name(int __argc__, Object** __argv__) { \ |
104 BUILTIN_1(name, a0) \ | 104 Handle<Object> receiver(&__argv__[0]); |
105 Object* a1 = BUILTIN_ARG(2); | |
106 | |
107 | |
108 #define BUILTIN_3(name, a0, a1, a2) \ | |
109 BUILTIN_2(name, a0, a1) \ | |
110 Object* a2 = BUILTIN_ARG(3); | |
111 | 105 |
112 | 106 |
113 // Use an inline function to avoid evaluating the index (n) more than | 107 // Use an inline function to avoid evaluating the index (n) more than |
114 // once in the BUILTIN_ARG macro. | 108 // once in the BUILTIN_ARG macro. |
115 static inline Object* __builtin_arg__(int n, int argc, Object** argv) { | 109 static inline Object* __builtin_arg__(int n, int argc, Object** argv) { |
116 ASSERT(n >= 0); | 110 ASSERT(n >= 0); |
117 return (argc > n) ? argv[-n] : Heap::undefined_value(); | 111 return (argc > n) ? argv[-n] : Heap::undefined_value(); |
118 } | 112 } |
119 | 113 |
120 | 114 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 code = function->code(); | 159 code = function->code(); |
166 *resolved = true; | 160 *resolved = true; |
167 } | 161 } |
168 } | 162 } |
169 } | 163 } |
170 | 164 |
171 return Handle<Code>(code); | 165 return Handle<Code>(code); |
172 } | 166 } |
173 | 167 |
174 | 168 |
175 BUILTIN_0(Illegal) { | 169 BUILTIN(Illegal) { |
176 UNREACHABLE(); | 170 UNREACHABLE(); |
177 } | 171 } |
178 BUILTIN_END | 172 BUILTIN_END |
179 | 173 |
180 | 174 |
181 BUILTIN_0(EmptyFunction) { | 175 BUILTIN(EmptyFunction) { |
182 } | 176 } |
183 BUILTIN_END | 177 BUILTIN_END |
184 | 178 |
185 | 179 |
186 BUILTIN_0(ArrayCode) { | 180 BUILTIN(ArrayCode) { |
187 JSArray* array; | 181 JSArray* array; |
188 if (is_construct) { | 182 if (is_construct) { |
189 array = JSArray::cast(*receiver); | 183 array = JSArray::cast(*receiver); |
190 } else { | 184 } else { |
191 // Allocate the JS Array | 185 // Allocate the JS Array |
192 JSFunction* constructor = | 186 JSFunction* constructor = |
193 Top::context()->global_context()->array_function(); | 187 Top::context()->global_context()->array_function(); |
194 Object* obj = Heap::AllocateJSObject(constructor); | 188 Object* obj = Heap::AllocateJSObject(constructor); |
195 if (obj->IsFailure()) return obj; | 189 if (obj->IsFailure()) return obj; |
196 array = JSArray::cast(obj); | 190 array = JSArray::cast(obj); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 | 228 |
235 // Set length and elements on the array. | 229 // Set length and elements on the array. |
236 array->set_elements(FixedArray::cast(obj)); | 230 array->set_elements(FixedArray::cast(obj)); |
237 array->set_length(len); | 231 array->set_length(len); |
238 | 232 |
239 return array; | 233 return array; |
240 } | 234 } |
241 BUILTIN_END | 235 BUILTIN_END |
242 | 236 |
243 | 237 |
244 BUILTIN_0(ArrayPush) { | 238 NEW_BUILTIN(ArrayPush) { |
245 JSArray* array = JSArray::cast(*receiver); | 239 JSArray* array = JSArray::cast(*receiver); |
246 ASSERT(array->HasFastElements()); | 240 ASSERT(array->HasFastElements()); |
247 | 241 |
248 // Make sure we have space for the elements. | 242 // Make sure we have space for the elements. |
249 int len = Smi::cast(array->length())->value(); | 243 int len = Smi::cast(array->length())->value(); |
250 | 244 |
251 // Set new length. | 245 // Set new length. |
252 int new_length = len + __argc__ - 1; | 246 int new_length = len + __argc__ - 1; |
253 FixedArray* elms = FixedArray::cast(array->elements()); | 247 FixedArray* elms = FixedArray::cast(array->elements()); |
254 | 248 |
(...skipping 18 matching lines...) Expand all Loading... |
273 // Set the new backing storage. | 267 // Set the new backing storage. |
274 array->set_elements(new_elms); | 268 array->set_elements(new_elms); |
275 } | 269 } |
276 // Set the length. | 270 // Set the length. |
277 array->set_length(Smi::FromInt(new_length)); | 271 array->set_length(Smi::FromInt(new_length)); |
278 return array->length(); | 272 return array->length(); |
279 } | 273 } |
280 BUILTIN_END | 274 BUILTIN_END |
281 | 275 |
282 | 276 |
283 BUILTIN_0(ArrayPop) { | 277 NEW_BUILTIN(ArrayPop) { |
284 JSArray* array = JSArray::cast(*receiver); | 278 JSArray* array = JSArray::cast(*receiver); |
285 ASSERT(array->HasFastElements()); | 279 ASSERT(array->HasFastElements()); |
286 Object* undefined = Heap::undefined_value(); | 280 Object* undefined = Heap::undefined_value(); |
287 | 281 |
288 int len = Smi::cast(array->length())->value(); | 282 int len = Smi::cast(array->length())->value(); |
289 if (len == 0) return undefined; | 283 if (len == 0) return undefined; |
290 | 284 |
291 // Get top element | 285 // Get top element |
292 FixedArray* elms = FixedArray::cast(array->elements()); | 286 FixedArray* elms = FixedArray::cast(array->elements()); |
293 Object* top = elms->get(len - 1); | 287 Object* top = elms->get(len - 1); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 *arg = current; | 352 *arg = current; |
359 break; | 353 break; |
360 } | 354 } |
361 } | 355 } |
362 if (current == Heap::null_value()) *arg = Heap::undefined_value(); | 356 if (current == Heap::null_value()) *arg = Heap::undefined_value(); |
363 } | 357 } |
364 return holder; | 358 return holder; |
365 } | 359 } |
366 | 360 |
367 | 361 |
368 BUILTIN_0(HandleApiCall) { | 362 BUILTIN(HandleApiCall) { |
369 HandleScope scope; | 363 HandleScope scope; |
370 | 364 |
371 // TODO(1238487): This is not nice. We need to get rid of this | 365 // TODO(1238487): This is not nice. We need to get rid of this |
372 // kludgy behavior and start handling API calls in a more direct | 366 // kludgy behavior and start handling API calls in a more direct |
373 // way - maybe compile specialized stubs lazily?. | 367 // way - maybe compile specialized stubs lazily?. |
374 Handle<JSFunction> function = | 368 Handle<JSFunction> function = |
375 Handle<JSFunction>(JSFunction::cast(Builtins::builtin_passed_function)); | 369 Handle<JSFunction>(JSFunction::cast(Builtins::builtin_passed_function)); |
376 | 370 |
377 if (is_construct) { | 371 if (is_construct) { |
378 Handle<FunctionTemplateInfo> desc = | 372 Handle<FunctionTemplateInfo> desc = |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 if (!is_construct || result->IsJSObject()) return result; | 432 if (!is_construct || result->IsJSObject()) return result; |
439 } | 433 } |
440 | 434 |
441 return *receiver; | 435 return *receiver; |
442 } | 436 } |
443 BUILTIN_END | 437 BUILTIN_END |
444 | 438 |
445 | 439 |
446 // Handle calls to non-function objects created through the API that | 440 // Handle calls to non-function objects created through the API that |
447 // support calls. | 441 // support calls. |
448 BUILTIN_0(HandleApiCallAsFunction) { | 442 BUILTIN(HandleApiCallAsFunction) { |
449 // Non-functions are never called as constructors. | 443 // Non-functions are never called as constructors. |
450 ASSERT(!is_construct); | 444 ASSERT(!is_construct); |
451 | 445 |
452 // Get the object called. | 446 // Get the object called. |
453 JSObject* obj = JSObject::cast(*receiver); | 447 JSObject* obj = JSObject::cast(*receiver); |
454 | 448 |
455 // Get the invocation callback from the function descriptor that was | 449 // Get the invocation callback from the function descriptor that was |
456 // used to create the called object. | 450 // used to create the called object. |
457 ASSERT(obj->map()->has_instance_call_handler()); | 451 ASSERT(obj->map()->has_instance_call_handler()); |
458 JSFunction* constructor = JSFunction::cast(obj->map()->constructor()); | 452 JSFunction* constructor = JSFunction::cast(obj->map()->constructor()); |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
743 if (entry->contains(pc)) { | 737 if (entry->contains(pc)) { |
744 return names_[i]; | 738 return names_[i]; |
745 } | 739 } |
746 } | 740 } |
747 } | 741 } |
748 return NULL; | 742 return NULL; |
749 } | 743 } |
750 | 744 |
751 | 745 |
752 } } // namespace v8::internal | 746 } } // namespace v8::internal |
OLD | NEW |