| 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 |