Chromium Code Reviews| 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 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 350 } | 350 } |
| 351 return param_data; | 351 return param_data; |
| 352 } | 352 } |
| 353 } | 353 } |
| 354 | 354 |
| 355 | 355 |
| 356 RUNTIME_FUNCTION(Runtime_FunctionBindArguments) { | 356 RUNTIME_FUNCTION(Runtime_FunctionBindArguments) { |
| 357 HandleScope scope(isolate); | 357 HandleScope scope(isolate); |
| 358 DCHECK(args.length() == 4); | 358 DCHECK(args.length() == 4); |
| 359 CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0); | 359 CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0); |
| 360 CONVERT_ARG_HANDLE_CHECKED(Object, bindee, 1); | 360 CONVERT_ARG_HANDLE_CHECKED(Object, bindee, 1); |
|
Igor Sheludko
2015/10/01 08:03:35
While you are here: it looks like bindee must be a
mvstanton
2015/10/01 11:23:01
Good idea, done.
| |
| 361 CONVERT_ARG_HANDLE_CHECKED(Object, this_object, 2); | 361 CONVERT_ARG_HANDLE_CHECKED(Object, this_object, 2); |
| 362 CONVERT_NUMBER_ARG_HANDLE_CHECKED(new_length, 3); | 362 CONVERT_NUMBER_ARG_HANDLE_CHECKED(new_length, 3); |
| 363 | 363 |
| 364 // TODO(lrn): Create bound function in C++ code from premade shared info. | 364 // TODO(lrn): Create bound function in C++ code from premade shared info. |
| 365 bound_function->shared()->set_bound(true); | 365 bound_function->shared()->set_bound(true); |
| 366 bound_function->shared()->set_optimized_code_map(Smi::FromInt(0)); | 366 bound_function->shared()->set_optimized_code_map(Smi::FromInt(0)); |
| 367 bound_function->shared()->set_inferred_name(isolate->heap()->empty_string()); | 367 bound_function->shared()->set_inferred_name(isolate->heap()->empty_string()); |
| 368 // Get all arguments of calling function (Function.prototype.bind). | 368 // Get all arguments of calling function (Function.prototype.bind). |
| 369 int argc = 0; | 369 int argc = 0; |
| 370 base::SmartArrayPointer<Handle<Object>> arguments = | 370 base::SmartArrayPointer<Handle<Object>> arguments = |
| 371 Runtime::GetCallerArguments(isolate, 0, &argc); | 371 Runtime::GetCallerArguments(isolate, 0, &argc); |
| 372 // Don't count the this-arg. | 372 // Don't count the this-arg. |
| 373 if (argc > 0) { | 373 if (argc > 0) { |
| 374 RUNTIME_ASSERT(arguments[0].is_identical_to(this_object)); | 374 RUNTIME_ASSERT(arguments[0].is_identical_to(this_object)); |
| 375 argc--; | 375 argc--; |
| 376 } else { | 376 } else { |
| 377 RUNTIME_ASSERT(this_object->IsUndefined()); | 377 RUNTIME_ASSERT(this_object->IsUndefined()); |
| 378 } | 378 } |
| 379 // Initialize array of bindings (function, this, and any existing arguments | 379 // Initialize array of bindings (function, this, and any existing arguments |
| 380 // if the function was already bound). | 380 // if the function was already bound). |
| 381 Handle<FixedArray> new_bindings; | 381 Handle<BindingsArray> new_bindings; |
| 382 int i; | 382 int i; |
|
Igor Sheludko
2015/10/01 08:03:35
Suggestion for better readability: int out_index =
mvstanton
2015/10/01 11:23:01
Done.
| |
| 383 Handle<TypeFeedbackVector> vector( | |
| 384 bound_function->shared()->feedback_vector()); | |
| 383 if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) { | 385 if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) { |
| 384 Handle<FixedArray> old_bindings( | 386 Handle<BindingsArray> old_bindings( |
| 385 JSFunction::cast(*bindee)->function_bindings()); | 387 JSFunction::cast(*bindee)->function_bindings()); |
| 386 RUNTIME_ASSERT(old_bindings->length() > JSFunction::kBoundFunctionIndex); | 388 RUNTIME_ASSERT(old_bindings->bindings_count() >= 0); |
| 387 new_bindings = | 389 bindee = Handle<JSReceiver>(old_bindings->bound_function(), isolate); |
|
Igor Sheludko
2015/10/01 08:03:35
nit: bindee = handle(old_bindings->bound_function(
mvstanton
2015/10/01 11:23:01
Done.
| |
| 388 isolate->factory()->NewFixedArray(old_bindings->length() + argc); | 390 Handle<Object> old_bound_this = handle(old_bindings->bound_this(), isolate); |
|
Igor Sheludko
2015/10/01 08:03:35
nit: Handle<Object> old_bound_this(old_bindings->b
mvstanton
2015/10/01 11:23:01
Done.
| |
| 389 bindee = Handle<Object>(old_bindings->get(JSFunction::kBoundFunctionIndex), | 391 new_bindings = BindingsArray::New( |
| 390 isolate); | 392 isolate, vector, Handle<JSReceiver>::cast(bindee), old_bound_this, |
| 393 old_bindings->bindings_count() + argc); | |
| 391 i = 0; | 394 i = 0; |
|
Igor Sheludko
2015/10/01 08:03:35
Can be removed.
mvstanton
2015/10/01 11:23:01
Done.
| |
| 392 for (int n = old_bindings->length(); i < n; i++) { | 395 for (int n = old_bindings->bindings_count(); i < n; i++) { |
| 393 new_bindings->set(i, old_bindings->get(i)); | 396 new_bindings->set_binding(i, old_bindings->binding(i)); |
|
Igor Sheludko
2015/10/01 08:03:35
suggestion: new_bindings->set_binding(out_index, o
mvstanton
2015/10/01 11:23:01
Done.
| |
| 394 } | 397 } |
| 395 } else { | 398 } else { |
| 396 int array_size = JSFunction::kBoundArgumentsStartIndex + argc; | 399 new_bindings = BindingsArray::New( |
| 397 new_bindings = isolate->factory()->NewFixedArray(array_size); | 400 isolate, vector, Handle<JSReceiver>::cast(bindee), this_object, argc); |
| 398 new_bindings->set(JSFunction::kBoundFunctionIndex, *bindee); | 401 i = 0; |
|
Igor Sheludko
2015/10/01 08:03:35
Can be removed.
mvstanton
2015/10/01 11:23:01
Done.
| |
| 399 new_bindings->set(JSFunction::kBoundThisIndex, *this_object); | |
| 400 i = 2; | |
| 401 } | 402 } |
| 402 // Copy arguments, skipping the first which is "this_arg". | 403 // Copy arguments, skipping the first which is "this_arg". |
| 403 for (int j = 0; j < argc; j++, i++) { | 404 for (int j = 0; j < argc; j++, i++) { |
| 404 new_bindings->set(i, *arguments[j + 1]); | 405 new_bindings->set_binding(i, *arguments[j + 1]); |
| 405 } | 406 } |
| 406 new_bindings->set_map_no_write_barrier(isolate->heap()->fixed_array_map()); | 407 new_bindings->set_map_no_write_barrier(isolate->heap()->fixed_array_map()); |
| 407 bound_function->set_function_bindings(*new_bindings); | 408 bound_function->set_function_bindings(*new_bindings); |
| 408 | 409 |
| 409 // Update length. Have to remove the prototype first so that map migration | 410 // Update length. Have to remove the prototype first so that map migration |
| 410 // is happy about the number of fields. | 411 // is happy about the number of fields. |
| 411 RUNTIME_ASSERT(bound_function->RemovePrototype()); | 412 RUNTIME_ASSERT(bound_function->RemovePrototype()); |
| 412 | 413 |
| 413 // The new function should have the same [[Prototype]] as the bindee. | 414 // The new function should have the same [[Prototype]] as the bindee. |
| 414 Handle<Map> bound_function_map( | 415 Handle<Map> bound_function_map( |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 438 } | 439 } |
| 439 | 440 |
| 440 | 441 |
| 441 RUNTIME_FUNCTION(Runtime_BoundFunctionGetBindings) { | 442 RUNTIME_FUNCTION(Runtime_BoundFunctionGetBindings) { |
| 442 HandleScope handles(isolate); | 443 HandleScope handles(isolate); |
| 443 DCHECK(args.length() == 1); | 444 DCHECK(args.length() == 1); |
| 444 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0); | 445 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0); |
| 445 if (callable->IsJSFunction()) { | 446 if (callable->IsJSFunction()) { |
| 446 Handle<JSFunction> function = Handle<JSFunction>::cast(callable); | 447 Handle<JSFunction> function = Handle<JSFunction>::cast(callable); |
| 447 if (function->shared()->bound()) { | 448 if (function->shared()->bound()) { |
| 448 RUNTIME_ASSERT(function->function_bindings()->IsFixedArray()); | 449 RUNTIME_ASSERT(function->function_bindings()->IsBindingsArray()); |
| 449 Handle<FixedArray> bindings(function->function_bindings()); | 450 Handle<BindingsArray> bindings(function->function_bindings()); |
| 450 return *isolate->factory()->NewJSArrayWithElements(bindings); | 451 return *BindingsArray::CreateRuntimeBindings(bindings); |
| 451 } | 452 } |
| 452 } | 453 } |
| 453 return isolate->heap()->undefined_value(); | 454 return isolate->heap()->undefined_value(); |
| 454 } | 455 } |
| 455 | 456 |
| 456 | 457 |
| 457 RUNTIME_FUNCTION(Runtime_NewObjectFromBound) { | 458 RUNTIME_FUNCTION(Runtime_NewObjectFromBound) { |
| 458 HandleScope scope(isolate); | 459 HandleScope scope(isolate); |
| 459 DCHECK(args.length() == 1); | 460 DCHECK(args.length() == 1); |
| 460 // First argument is a function to use as a constructor. | 461 // First argument is a function to use as a constructor. |
| 461 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); | 462 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); |
| 462 RUNTIME_ASSERT(function->shared()->bound()); | 463 RUNTIME_ASSERT(function->shared()->bound()); |
| 463 | 464 |
| 464 // The argument is a bound function. Extract its bound arguments | 465 // The argument is a bound function. Extract its bound arguments |
| 465 // and callable. | 466 // and callable. |
| 466 Handle<FixedArray> bound_args = | 467 Handle<BindingsArray> bound_args = |
| 467 Handle<FixedArray>(FixedArray::cast(function->function_bindings())); | 468 handle(BindingsArray::cast(function->function_bindings())); |
| 468 int bound_argc = bound_args->length() - JSFunction::kBoundArgumentsStartIndex; | 469 int bound_argc = bound_args->bindings_count(); |
| 469 Handle<Object> bound_function( | 470 Handle<Object> bound_function(bound_args->bound_function(), isolate); |
| 470 JSReceiver::cast(bound_args->get(JSFunction::kBoundFunctionIndex)), | |
| 471 isolate); | |
| 472 DCHECK(!bound_function->IsJSFunction() || | 471 DCHECK(!bound_function->IsJSFunction() || |
| 473 !Handle<JSFunction>::cast(bound_function)->shared()->bound()); | 472 !Handle<JSFunction>::cast(bound_function)->shared()->bound()); |
| 474 | 473 |
| 475 int total_argc = 0; | 474 int total_argc = 0; |
| 476 base::SmartArrayPointer<Handle<Object>> param_data = | 475 base::SmartArrayPointer<Handle<Object>> param_data = |
| 477 Runtime::GetCallerArguments(isolate, bound_argc, &total_argc); | 476 Runtime::GetCallerArguments(isolate, bound_argc, &total_argc); |
| 478 for (int i = 0; i < bound_argc; i++) { | 477 for (int i = 0; i < bound_argc; i++) { |
| 479 param_data[i] = Handle<Object>( | 478 param_data[i] = Handle<Object>(bound_args->binding(i), isolate); |
|
Igor Sheludko
2015/10/01 08:03:35
nit: param_data[i] = handle(bound_args->binding(i)
mvstanton
2015/10/01 11:23:01
Done.
| |
| 480 bound_args->get(JSFunction::kBoundArgumentsStartIndex + i), isolate); | |
| 481 } | 479 } |
| 482 | 480 |
| 483 Handle<Object> result; | 481 Handle<Object> result; |
| 484 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 482 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 485 isolate, result, Execution::New(isolate, bound_function, bound_function, | 483 isolate, result, Execution::New(isolate, bound_function, bound_function, |
| 486 total_argc, param_data.get())); | 484 total_argc, param_data.get())); |
| 487 return *result; | 485 return *result; |
| 488 } | 486 } |
| 489 | 487 |
| 490 | 488 |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 604 | 602 |
| 605 | 603 |
| 606 RUNTIME_FUNCTION(Runtime_ThrowStrongModeTooFewArguments) { | 604 RUNTIME_FUNCTION(Runtime_ThrowStrongModeTooFewArguments) { |
| 607 HandleScope scope(isolate); | 605 HandleScope scope(isolate); |
| 608 DCHECK(args.length() == 0); | 606 DCHECK(args.length() == 0); |
| 609 THROW_NEW_ERROR_RETURN_FAILURE(isolate, | 607 THROW_NEW_ERROR_RETURN_FAILURE(isolate, |
| 610 NewTypeError(MessageTemplate::kStrongArity)); | 608 NewTypeError(MessageTemplate::kStrongArity)); |
| 611 } | 609 } |
| 612 } // namespace internal | 610 } // namespace internal |
| 613 } // namespace v8 | 611 } // namespace v8 |
| OLD | NEW |