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