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 |