| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/runtime/runtime-utils.h" | 5 #include "src/runtime/runtime-utils.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/arguments.h" | 8 #include "src/arguments.h" |
| 9 #include "src/compiler.h" | 9 #include "src/compiler.h" |
| 10 #include "src/deoptimizer.h" | 10 #include "src/deoptimizer.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 RUNTIME_ASSERT(f->RemovePrototype()); | 46 RUNTIME_ASSERT(f->RemovePrototype()); |
| 47 f->shared()->set_construct_stub( | 47 f->shared()->set_construct_stub( |
| 48 *isolate->builtins()->ConstructedNonConstructable()); | 48 *isolate->builtins()->ConstructedNonConstructable()); |
| 49 | 49 |
| 50 return isolate->heap()->undefined_value(); | 50 return isolate->heap()->undefined_value(); |
| 51 } | 51 } |
| 52 | 52 |
| 53 | 53 |
| 54 RUNTIME_FUNCTION(Runtime_FunctionGetScript) { | 54 RUNTIME_FUNCTION(Runtime_FunctionGetScript) { |
| 55 HandleScope scope(isolate); | 55 HandleScope scope(isolate); |
| 56 DCHECK(args.length() == 1); | 56 DCHECK_EQ(1, args.length()); |
| 57 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0); |
| 57 | 58 |
| 58 CONVERT_ARG_CHECKED(JSFunction, fun, 0); | 59 if (function->IsJSBoundFunction()) return isolate->heap()->undefined_value(); |
| 59 Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate); | 60 Handle<Object> script(Handle<JSFunction>::cast(function)->shared()->script(), |
| 61 isolate); |
| 60 if (!script->IsScript()) return isolate->heap()->undefined_value(); | 62 if (!script->IsScript()) return isolate->heap()->undefined_value(); |
| 61 | |
| 62 return *Script::GetWrapper(Handle<Script>::cast(script)); | 63 return *Script::GetWrapper(Handle<Script>::cast(script)); |
| 63 } | 64 } |
| 64 | 65 |
| 65 | 66 |
| 66 RUNTIME_FUNCTION(Runtime_FunctionGetSourceCode) { | 67 RUNTIME_FUNCTION(Runtime_FunctionGetSourceCode) { |
| 67 HandleScope scope(isolate); | 68 HandleScope scope(isolate); |
| 68 DCHECK(args.length() == 1); | 69 DCHECK_EQ(1, args.length()); |
| 69 | 70 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0); |
| 70 CONVERT_ARG_HANDLE_CHECKED(JSFunction, f, 0); | 71 if (function->IsJSBoundFunction()) return isolate->heap()->undefined_value(); |
| 71 Handle<SharedFunctionInfo> shared(f->shared()); | 72 return *Handle<JSFunction>::cast(function)->shared()->GetSourceCode(); |
| 72 return *shared->GetSourceCode(); | |
| 73 } | 73 } |
| 74 | 74 |
| 75 | 75 |
| 76 RUNTIME_FUNCTION(Runtime_FunctionGetScriptSourcePosition) { | 76 RUNTIME_FUNCTION(Runtime_FunctionGetScriptSourcePosition) { |
| 77 SealHandleScope shs(isolate); | 77 SealHandleScope shs(isolate); |
| 78 DCHECK(args.length() == 1); | 78 DCHECK(args.length() == 1); |
| 79 | 79 |
| 80 CONVERT_ARG_CHECKED(JSFunction, fun, 0); | 80 CONVERT_ARG_CHECKED(JSFunction, fun, 0); |
| 81 int pos = fun->shared()->start_position(); | 81 int pos = fun->shared()->start_position(); |
| 82 return Smi::FromInt(pos); | 82 return Smi::FromInt(pos); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 | 145 |
| 146 RUNTIME_FUNCTION(Runtime_SetCode) { | 146 RUNTIME_FUNCTION(Runtime_SetCode) { |
| 147 HandleScope scope(isolate); | 147 HandleScope scope(isolate); |
| 148 DCHECK(args.length() == 2); | 148 DCHECK(args.length() == 2); |
| 149 | 149 |
| 150 CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0); | 150 CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0); |
| 151 CONVERT_ARG_HANDLE_CHECKED(JSFunction, source, 1); | 151 CONVERT_ARG_HANDLE_CHECKED(JSFunction, source, 1); |
| 152 | 152 |
| 153 Handle<SharedFunctionInfo> target_shared(target->shared()); | 153 Handle<SharedFunctionInfo> target_shared(target->shared()); |
| 154 Handle<SharedFunctionInfo> source_shared(source->shared()); | 154 Handle<SharedFunctionInfo> source_shared(source->shared()); |
| 155 RUNTIME_ASSERT(!source_shared->bound()); | |
| 156 | 155 |
| 157 if (!Compiler::Compile(source, KEEP_EXCEPTION)) { | 156 if (!Compiler::Compile(source, KEEP_EXCEPTION)) { |
| 158 return isolate->heap()->exception(); | 157 return isolate->heap()->exception(); |
| 159 } | 158 } |
| 160 | 159 |
| 161 // Mark both, the source and the target, as un-flushable because the | 160 // Mark both, the source and the target, as un-flushable because the |
| 162 // shared unoptimized code makes them impossible to enqueue in a list. | 161 // shared unoptimized code makes them impossible to enqueue in a list. |
| 163 DCHECK(target_shared->code()->gc_metadata() == NULL); | 162 DCHECK(target_shared->code()->gc_metadata() == NULL); |
| 164 DCHECK(source_shared->code()->gc_metadata() == NULL); | 163 DCHECK(source_shared->code()->gc_metadata() == NULL); |
| 165 target_shared->set_dont_flush(true); | 164 target_shared->set_dont_flush(true); |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 302 NewArray<Handle<Object> >(*total_argc)); | 301 NewArray<Handle<Object> >(*total_argc)); |
| 303 for (int i = 0; i < args_count; i++) { | 302 for (int i = 0; i < args_count; i++) { |
| 304 Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate); | 303 Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate); |
| 305 param_data[prefix_argc + i] = val; | 304 param_data[prefix_argc + i] = val; |
| 306 } | 305 } |
| 307 return param_data; | 306 return param_data; |
| 308 } | 307 } |
| 309 } | 308 } |
| 310 | 309 |
| 311 | 310 |
| 312 RUNTIME_FUNCTION(Runtime_FunctionBindArguments) { | |
| 313 HandleScope scope(isolate); | |
| 314 DCHECK(args.length() == 5); | |
| 315 CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0); | |
| 316 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, bindee, 1); | |
| 317 CONVERT_ARG_HANDLE_CHECKED(Object, this_object, 2); | |
| 318 CONVERT_NUMBER_ARG_HANDLE_CHECKED(new_length, 3); | |
| 319 CONVERT_ARG_HANDLE_CHECKED(Object, proto, 4); | |
| 320 | |
| 321 // TODO(lrn): Create bound function in C++ code from premade shared info. | |
| 322 bound_function->shared()->set_bound(true); | |
| 323 bound_function->shared()->set_optimized_code_map( | |
| 324 isolate->heap()->cleared_optimized_code_map()); | |
| 325 bound_function->shared()->set_inferred_name(isolate->heap()->empty_string()); | |
| 326 bound_function->shared()->set_construct_stub( | |
| 327 *isolate->builtins()->JSBuiltinsConstructStub()); | |
| 328 // Get all arguments of calling function (Function.prototype.bind). | |
| 329 int argc = 0; | |
| 330 base::SmartArrayPointer<Handle<Object>> arguments = | |
| 331 Runtime::GetCallerArguments(isolate, 0, &argc); | |
| 332 // Don't count the this-arg. | |
| 333 if (argc > 0) { | |
| 334 RUNTIME_ASSERT(arguments[0].is_identical_to(this_object)); | |
| 335 argc--; | |
| 336 } else { | |
| 337 RUNTIME_ASSERT(this_object->IsUndefined()); | |
| 338 } | |
| 339 // Initialize array of bindings (function, this, and any existing arguments | |
| 340 // if the function was already bound). | |
| 341 Handle<BindingsArray> new_bindings; | |
| 342 int out_index = 0; | |
| 343 Handle<TypeFeedbackVector> vector( | |
| 344 bound_function->shared()->feedback_vector()); | |
| 345 if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) { | |
| 346 Handle<BindingsArray> old_bindings( | |
| 347 JSFunction::cast(*bindee)->function_bindings()); | |
| 348 RUNTIME_ASSERT(old_bindings->bindings_count() >= 0); | |
| 349 bindee = handle(old_bindings->bound_function(), isolate); | |
| 350 Handle<Object> old_bound_this(old_bindings->bound_this(), isolate); | |
| 351 new_bindings = BindingsArray::New(isolate, vector, bindee, old_bound_this, | |
| 352 old_bindings->bindings_count() + argc); | |
| 353 for (int n = old_bindings->bindings_count(); out_index < n; out_index++) { | |
| 354 new_bindings->set_binding(out_index, old_bindings->binding(out_index)); | |
| 355 } | |
| 356 } else { | |
| 357 new_bindings = | |
| 358 BindingsArray::New(isolate, vector, bindee, this_object, argc); | |
| 359 } | |
| 360 // Copy arguments, skipping the first which is "this_arg". | |
| 361 for (int j = 0; j < argc; j++, out_index++) { | |
| 362 new_bindings->set_binding(out_index, *arguments[j + 1]); | |
| 363 } | |
| 364 new_bindings->set_map_no_write_barrier(isolate->heap()->fixed_array_map()); | |
| 365 bound_function->set_function_bindings(*new_bindings); | |
| 366 | |
| 367 // Update length. Have to remove the prototype first so that map migration | |
| 368 // is happy about the number of fields. | |
| 369 RUNTIME_ASSERT(bound_function->RemovePrototype()); | |
| 370 | |
| 371 // The new function should have the given prototype. | |
| 372 Handle<Map> bound_function_map = | |
| 373 bindee->IsConstructor() | |
| 374 ? isolate->bound_function_with_constructor_map() | |
| 375 : isolate->bound_function_without_constructor_map(); | |
| 376 if (bound_function_map->prototype() != *proto) { | |
| 377 bound_function_map = Map::TransitionToPrototype(bound_function_map, proto, | |
| 378 REGULAR_PROTOTYPE); | |
| 379 } | |
| 380 JSObject::MigrateToMap(bound_function, bound_function_map); | |
| 381 DCHECK_EQ(bindee->IsConstructor(), bound_function->IsConstructor()); | |
| 382 | |
| 383 Handle<String> length_string = isolate->factory()->length_string(); | |
| 384 // These attributes must be kept in sync with how the bootstrapper | |
| 385 // configures the bound_function_map retrieved above. | |
| 386 // We use ...IgnoreAttributes() here because of length's read-onliness. | |
| 387 PropertyAttributes attr = | |
| 388 static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY); | |
| 389 RETURN_FAILURE_ON_EXCEPTION( | |
| 390 isolate, JSObject::SetOwnPropertyIgnoreAttributes( | |
| 391 bound_function, length_string, new_length, attr)); | |
| 392 return *bound_function; | |
| 393 } | |
| 394 | |
| 395 | |
| 396 RUNTIME_FUNCTION(Runtime_BoundFunctionGetBindings) { | |
| 397 HandleScope handles(isolate); | |
| 398 DCHECK(args.length() == 1); | |
| 399 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0); | |
| 400 if (callable->IsJSFunction()) { | |
| 401 Handle<JSFunction> function = Handle<JSFunction>::cast(callable); | |
| 402 if (function->shared()->bound()) { | |
| 403 RUNTIME_ASSERT(function->function_bindings()->IsBindingsArray()); | |
| 404 Handle<BindingsArray> bindings(function->function_bindings()); | |
| 405 return *BindingsArray::CreateRuntimeBindings(bindings); | |
| 406 } | |
| 407 } | |
| 408 return isolate->heap()->undefined_value(); | |
| 409 } | |
| 410 | |
| 411 | |
| 412 RUNTIME_FUNCTION(Runtime_NewObjectFromBound) { | |
| 413 HandleScope scope(isolate); | |
| 414 DCHECK(args.length() == 1); | |
| 415 // First argument is a function to use as a constructor. | |
| 416 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); | |
| 417 RUNTIME_ASSERT(function->shared()->bound()); | |
| 418 | |
| 419 // The argument is a bound function. Extract its bound arguments | |
| 420 // and callable. | |
| 421 Handle<BindingsArray> bound_args = | |
| 422 handle(BindingsArray::cast(function->function_bindings())); | |
| 423 int bound_argc = bound_args->bindings_count(); | |
| 424 Handle<Object> bound_function(bound_args->bound_function(), isolate); | |
| 425 DCHECK(!bound_function->IsJSFunction() || | |
| 426 !Handle<JSFunction>::cast(bound_function)->shared()->bound()); | |
| 427 | |
| 428 int total_argc = 0; | |
| 429 base::SmartArrayPointer<Handle<Object>> param_data = | |
| 430 Runtime::GetCallerArguments(isolate, bound_argc, &total_argc); | |
| 431 for (int i = 0; i < bound_argc; i++) { | |
| 432 param_data[i] = handle(bound_args->binding(i), isolate); | |
| 433 } | |
| 434 | |
| 435 Handle<Object> result; | |
| 436 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
| 437 isolate, result, Execution::New(isolate, bound_function, bound_function, | |
| 438 total_argc, param_data.get())); | |
| 439 return *result; | |
| 440 } | |
| 441 | |
| 442 | |
| 443 RUNTIME_FUNCTION(Runtime_Call) { | 311 RUNTIME_FUNCTION(Runtime_Call) { |
| 444 HandleScope scope(isolate); | 312 HandleScope scope(isolate); |
| 445 DCHECK_LE(2, args.length()); | 313 DCHECK_LE(2, args.length()); |
| 446 int const argc = args.length() - 2; | 314 int const argc = args.length() - 2; |
| 447 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, target, 0); | 315 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, target, 0); |
| 448 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1); | 316 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1); |
| 449 ScopedVector<Handle<Object>> argv(argc); | 317 ScopedVector<Handle<Object>> argv(argc); |
| 450 for (int i = 0; i < argc; ++i) { | 318 for (int i = 0; i < argc; ++i) { |
| 451 argv[i] = args.at<Object>(2 + i); | 319 argv[i] = args.at<Object>(2 + i); |
| 452 } | 320 } |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 520 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0); | 388 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0); |
| 521 if (receiver->IsNull() || receiver->IsUndefined()) { | 389 if (receiver->IsNull() || receiver->IsUndefined()) { |
| 522 return isolate->global_proxy(); | 390 return isolate->global_proxy(); |
| 523 } | 391 } |
| 524 return *Object::ToObject(isolate, receiver).ToHandleChecked(); | 392 return *Object::ToObject(isolate, receiver).ToHandleChecked(); |
| 525 } | 393 } |
| 526 | 394 |
| 527 | 395 |
| 528 RUNTIME_FUNCTION(Runtime_IsFunction) { | 396 RUNTIME_FUNCTION(Runtime_IsFunction) { |
| 529 SealHandleScope shs(isolate); | 397 SealHandleScope shs(isolate); |
| 530 DCHECK(args.length() == 1); | 398 DCHECK_EQ(1, args.length()); |
| 531 CONVERT_ARG_CHECKED(Object, obj, 0); | 399 CONVERT_ARG_CHECKED(Object, object, 0); |
| 532 return isolate->heap()->ToBoolean(obj->IsJSFunction()); | 400 return isolate->heap()->ToBoolean(object->IsFunction()); |
| 533 } | 401 } |
| 534 | 402 |
| 535 | 403 |
| 536 RUNTIME_FUNCTION(Runtime_ThrowStrongModeTooFewArguments) { | 404 RUNTIME_FUNCTION(Runtime_ThrowStrongModeTooFewArguments) { |
| 537 HandleScope scope(isolate); | 405 HandleScope scope(isolate); |
| 538 DCHECK(args.length() == 0); | 406 DCHECK(args.length() == 0); |
| 539 THROW_NEW_ERROR_RETURN_FAILURE(isolate, | 407 THROW_NEW_ERROR_RETURN_FAILURE(isolate, |
| 540 NewTypeError(MessageTemplate::kStrongArity)); | 408 NewTypeError(MessageTemplate::kStrongArity)); |
| 541 } | 409 } |
| 542 | 410 |
| 543 | 411 |
| 544 RUNTIME_FUNCTION(Runtime_FunctionToString) { | 412 RUNTIME_FUNCTION(Runtime_FunctionToString) { |
| 545 HandleScope scope(isolate); | 413 HandleScope scope(isolate); |
| 546 DCHECK_EQ(1, args.length()); | 414 DCHECK_EQ(1, args.length()); |
| 547 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); | 415 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0); |
| 548 return *JSFunction::ToString(function); | 416 return function->IsJSBoundFunction() |
| 417 ? *JSBoundFunction::ToString( |
| 418 Handle<JSBoundFunction>::cast(function)) |
| 419 : *JSFunction::ToString(Handle<JSFunction>::cast(function)); |
| 549 } | 420 } |
| 550 | 421 |
| 551 } // namespace internal | 422 } // namespace internal |
| 552 } // namespace v8 | 423 } // namespace v8 |
| OLD | NEW |