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/frames-inl.h" | 9 #include "src/frames-inl.h" |
10 #include "src/isolate-inl.h" | 10 #include "src/isolate-inl.h" |
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
397 } | 397 } |
398 | 398 |
399 RETURN_FAILURE_ON_EXCEPTION( | 399 RETURN_FAILURE_ON_EXCEPTION( |
400 isolate, JSObject::SetOwnPropertyIgnoreAttributes( | 400 isolate, JSObject::SetOwnPropertyIgnoreAttributes( |
401 Handle<JSObject>::cast(holder), name, value, attr)); | 401 Handle<JSObject>::cast(holder), name, value, attr)); |
402 | 402 |
403 return *value; | 403 return *value; |
404 } | 404 } |
405 | 405 |
406 | 406 |
407 static Handle<JSObject> NewSloppyArguments(Isolate* isolate, | 407 namespace { |
408 Handle<JSFunction> callee, | 408 |
409 Object** parameters, | 409 template <typename T> |
410 int argument_count) { | 410 Handle<JSObject> NewSloppyArguments(Isolate* isolate, Handle<JSFunction> callee, |
411 T parameters, int argument_count) { | |
411 CHECK(!IsSubclassConstructor(callee->shared()->kind())); | 412 CHECK(!IsSubclassConstructor(callee->shared()->kind())); |
412 DCHECK(callee->has_simple_parameters()); | 413 DCHECK(callee->has_simple_parameters()); |
413 Handle<JSObject> result = | 414 Handle<JSObject> result = |
414 isolate->factory()->NewArgumentsObject(callee, argument_count); | 415 isolate->factory()->NewArgumentsObject(callee, argument_count); |
415 | 416 |
416 // Allocate the elements if needed. | 417 // Allocate the elements if needed. |
417 int parameter_count = callee->shared()->internal_formal_parameter_count(); | 418 int parameter_count = callee->shared()->internal_formal_parameter_count(); |
418 if (argument_count > 0) { | 419 if (argument_count > 0) { |
419 if (parameter_count > 0) { | 420 if (parameter_count > 0) { |
420 int mapped_count = Min(argument_count, parameter_count); | 421 int mapped_count = Min(argument_count, parameter_count); |
421 Handle<FixedArray> parameter_map = | 422 Handle<FixedArray> parameter_map = |
422 isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED); | 423 isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED); |
423 parameter_map->set_map(isolate->heap()->sloppy_arguments_elements_map()); | 424 parameter_map->set_map(isolate->heap()->sloppy_arguments_elements_map()); |
424 result->set_map(isolate->native_context()->fast_aliased_arguments_map()); | 425 result->set_map(isolate->native_context()->fast_aliased_arguments_map()); |
425 result->set_elements(*parameter_map); | 426 result->set_elements(*parameter_map); |
426 | 427 |
427 // Store the context and the arguments array at the beginning of the | 428 // Store the context and the arguments array at the beginning of the |
428 // parameter map. | 429 // parameter map. |
429 Handle<Context> context(isolate->context()); | 430 Handle<Context> context(isolate->context()); |
430 Handle<FixedArray> arguments = | 431 Handle<FixedArray> arguments = |
431 isolate->factory()->NewFixedArray(argument_count, NOT_TENURED); | 432 isolate->factory()->NewFixedArray(argument_count, NOT_TENURED); |
432 parameter_map->set(0, *context); | 433 parameter_map->set(0, *context); |
433 parameter_map->set(1, *arguments); | 434 parameter_map->set(1, *arguments); |
434 | 435 |
435 // Loop over the actual parameters backwards. | 436 // Loop over the actual parameters backwards. |
436 int index = argument_count - 1; | 437 int index = argument_count - 1; |
437 while (index >= mapped_count) { | 438 while (index >= mapped_count) { |
438 // These go directly in the arguments array and have no | 439 // These go directly in the arguments array and have no |
439 // corresponding slot in the parameter map. | 440 // corresponding slot in the parameter map. |
440 arguments->set(index, *(parameters - index - 1)); | 441 arguments->set(index, parameters[index]); |
441 --index; | 442 --index; |
442 } | 443 } |
443 | 444 |
444 Handle<ScopeInfo> scope_info(callee->shared()->scope_info()); | 445 Handle<ScopeInfo> scope_info(callee->shared()->scope_info()); |
445 while (index >= 0) { | 446 while (index >= 0) { |
446 // Detect duplicate names to the right in the parameter list. | 447 // Detect duplicate names to the right in the parameter list. |
447 Handle<String> name(scope_info->ParameterName(index)); | 448 Handle<String> name(scope_info->ParameterName(index)); |
448 int context_local_count = scope_info->ContextLocalCount(); | 449 int context_local_count = scope_info->ContextLocalCount(); |
449 bool duplicate = false; | 450 bool duplicate = false; |
450 for (int j = index + 1; j < parameter_count; ++j) { | 451 for (int j = index + 1; j < parameter_count; ++j) { |
451 if (scope_info->ParameterName(j) == *name) { | 452 if (scope_info->ParameterName(j) == *name) { |
452 duplicate = true; | 453 duplicate = true; |
453 break; | 454 break; |
454 } | 455 } |
455 } | 456 } |
456 | 457 |
457 if (duplicate) { | 458 if (duplicate) { |
458 // This goes directly in the arguments array with a hole in the | 459 // This goes directly in the arguments array with a hole in the |
459 // parameter map. | 460 // parameter map. |
460 arguments->set(index, *(parameters - index - 1)); | 461 arguments->set(index, parameters[index]); |
461 parameter_map->set_the_hole(index + 2); | 462 parameter_map->set_the_hole(index + 2); |
462 } else { | 463 } else { |
463 // The context index goes in the parameter map with a hole in the | 464 // The context index goes in the parameter map with a hole in the |
464 // arguments array. | 465 // arguments array. |
465 int context_index = -1; | 466 int context_index = -1; |
466 for (int j = 0; j < context_local_count; ++j) { | 467 for (int j = 0; j < context_local_count; ++j) { |
467 if (scope_info->ContextLocalName(j) == *name) { | 468 if (scope_info->ContextLocalName(j) == *name) { |
468 context_index = j; | 469 context_index = j; |
469 break; | 470 break; |
470 } | 471 } |
471 } | 472 } |
472 | 473 |
473 DCHECK(context_index >= 0); | 474 DCHECK(context_index >= 0); |
474 arguments->set_the_hole(index); | 475 arguments->set_the_hole(index); |
475 parameter_map->set( | 476 parameter_map->set( |
476 index + 2, | 477 index + 2, |
477 Smi::FromInt(Context::MIN_CONTEXT_SLOTS + context_index)); | 478 Smi::FromInt(Context::MIN_CONTEXT_SLOTS + context_index)); |
478 } | 479 } |
479 | 480 |
480 --index; | 481 --index; |
481 } | 482 } |
482 } else { | 483 } else { |
483 // If there is no aliasing, the arguments object elements are not | 484 // If there is no aliasing, the arguments object elements are not |
484 // special in any way. | 485 // special in any way. |
485 Handle<FixedArray> elements = | 486 Handle<FixedArray> elements = |
486 isolate->factory()->NewFixedArray(argument_count, NOT_TENURED); | 487 isolate->factory()->NewFixedArray(argument_count, NOT_TENURED); |
487 result->set_elements(*elements); | 488 result->set_elements(*elements); |
488 for (int i = 0; i < argument_count; ++i) { | 489 for (int i = 0; i < argument_count; ++i) { |
489 elements->set(i, *(parameters - i - 1)); | 490 elements->set(i, parameters[i]); |
490 } | 491 } |
491 } | 492 } |
492 } | 493 } |
493 return result; | 494 return result; |
494 } | 495 } |
495 | 496 |
496 | 497 |
497 static Handle<JSObject> NewStrictArguments(Isolate* isolate, | 498 template <typename T> |
498 Handle<JSFunction> callee, | 499 Handle<JSObject> NewStrictArguments(Isolate* isolate, Handle<JSFunction> callee, |
499 Object** parameters, | 500 T parameters, int argument_count) { |
500 int argument_count) { | |
501 Handle<JSObject> result = | 501 Handle<JSObject> result = |
502 isolate->factory()->NewArgumentsObject(callee, argument_count); | 502 isolate->factory()->NewArgumentsObject(callee, argument_count); |
503 | 503 |
504 if (argument_count > 0) { | 504 if (argument_count > 0) { |
505 Handle<FixedArray> array = | 505 Handle<FixedArray> array = |
506 isolate->factory()->NewUninitializedFixedArray(argument_count); | 506 isolate->factory()->NewUninitializedFixedArray(argument_count); |
507 DisallowHeapAllocation no_gc; | 507 DisallowHeapAllocation no_gc; |
508 WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc); | 508 WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc); |
509 for (int i = 0; i < argument_count; i++) { | 509 for (int i = 0; i < argument_count; i++) { |
510 array->set(i, *--parameters, mode); | 510 array->set(i, parameters[i], mode); |
511 } | 511 } |
512 result->set_elements(*array); | 512 result->set_elements(*array); |
513 } | 513 } |
514 return result; | 514 return result; |
515 } | 515 } |
516 | 516 |
517 | 517 |
518 RUNTIME_FUNCTION(Runtime_NewArguments) { | 518 class HandleArguments BASE_EMBEDDED { |
519 public: | |
520 explicit HandleArguments(Handle<Object>* array) : array_(array) {} | |
521 Object* operator[](int index) { return *array_[index]; } | |
522 | |
523 private: | |
524 Handle<Object>* array_; | |
525 }; | |
526 | |
527 | |
528 class ParameterArguments BASE_EMBEDDED { | |
529 public: | |
530 explicit ParameterArguments(Object** parameters) : parameters_(parameters) {} | |
531 Object*& operator[](int index) { return *(parameters_ - index - 1); } | |
532 | |
533 private: | |
534 Object** parameters_; | |
535 }; | |
536 | |
537 } // namespace | |
538 | |
539 | |
540 RUNTIME_FUNCTION(Runtime_NewSloppyArguments_Generic) { | |
519 HandleScope scope(isolate); | 541 HandleScope scope(isolate); |
520 DCHECK(args.length() == 1); | 542 DCHECK(args.length() == 1); |
521 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0); | 543 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0); |
522 JavaScriptFrameIterator it(isolate); | 544 // This generic runtime function can also be used when the caller has been |
523 | 545 // inlined, we use the slow but accurate deoptimization information. |
mvstanton
2015/09/16 06:54:22
nit: more exactly, Runtime::GetCallerArguments use
Michael Starzinger
2015/09/16 07:54:11
Done. I clarified the comment.
| |
524 // Find the frame that holds the actual arguments passed to the function. | 546 int argument_count = 0; |
525 it.AdvanceToArgumentsFrame(); | 547 base::SmartArrayPointer<Handle<Object>> arguments = |
526 JavaScriptFrame* frame = it.frame(); | 548 Runtime::GetCallerArguments(isolate, 0, &argument_count); |
527 | 549 HandleArguments argument_getter(arguments.get()); |
528 // Determine parameter location on the stack and dispatch on language mode. | 550 return *NewSloppyArguments(isolate, callee, argument_getter, argument_count); |
529 int argument_count = frame->GetArgumentsLength(); | |
530 Object** parameters = reinterpret_cast<Object**>(frame->GetParameterSlot(-1)); | |
531 | |
532 return (is_strict(callee->shared()->language_mode()) || | |
533 !callee->has_simple_parameters()) | |
534 ? *NewStrictArguments(isolate, callee, parameters, argument_count) | |
535 : *NewSloppyArguments(isolate, callee, parameters, argument_count); | |
536 } | 551 } |
537 | 552 |
538 | 553 |
554 RUNTIME_FUNCTION(Runtime_NewStrictArguments_Generic) { | |
555 HandleScope scope(isolate); | |
556 DCHECK(args.length() == 1); | |
557 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0); | |
558 // This generic runtime function can also be used when the caller has been | |
559 // inlined, we use the slow but accurate deoptimization information. | |
560 int argument_count = 0; | |
561 base::SmartArrayPointer<Handle<Object>> arguments = | |
562 Runtime::GetCallerArguments(isolate, 0, &argument_count); | |
563 HandleArguments argument_getter(arguments.get()); | |
564 return *NewStrictArguments(isolate, callee, argument_getter, argument_count); | |
565 } | |
566 | |
567 | |
539 RUNTIME_FUNCTION(Runtime_NewSloppyArguments) { | 568 RUNTIME_FUNCTION(Runtime_NewSloppyArguments) { |
540 HandleScope scope(isolate); | 569 HandleScope scope(isolate); |
541 DCHECK(args.length() == 3); | 570 DCHECK(args.length() == 3); |
542 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0); | 571 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0); |
543 Object** parameters = reinterpret_cast<Object**>(args[1]); | 572 Object** parameters = reinterpret_cast<Object**>(args[1]); |
544 CONVERT_SMI_ARG_CHECKED(argument_count, 2); | 573 CONVERT_SMI_ARG_CHECKED(argument_count, 2); |
545 #ifdef DEBUG | 574 #ifdef DEBUG |
546 // This runtime function does not materialize the correct arguments when the | 575 // This runtime function does not materialize the correct arguments when the |
547 // caller has been inlined, better make sure we are not hitting that case. | 576 // caller has been inlined, better make sure we are not hitting that case. |
548 List<JSFunction*> functions(1); | 577 List<JSFunction*> functions(1); |
549 JavaScriptFrameIterator it(isolate); | 578 JavaScriptFrameIterator it(isolate); |
550 it.frame()->GetFunctions(&functions); | 579 it.frame()->GetFunctions(&functions); |
551 DCHECK_EQ(1, functions.length()); | 580 DCHECK_EQ(1, functions.length()); |
552 #endif // DEBUG | 581 #endif // DEBUG |
553 return *NewSloppyArguments(isolate, callee, parameters, argument_count); | 582 ParameterArguments argument_getter(parameters); |
583 return *NewSloppyArguments(isolate, callee, argument_getter, argument_count); | |
554 } | 584 } |
555 | 585 |
556 | 586 |
557 RUNTIME_FUNCTION(Runtime_NewStrictArguments) { | 587 RUNTIME_FUNCTION(Runtime_NewStrictArguments) { |
558 HandleScope scope(isolate); | 588 HandleScope scope(isolate); |
559 DCHECK(args.length() == 3); | 589 DCHECK(args.length() == 3); |
560 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0) | 590 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0) |
561 Object** parameters = reinterpret_cast<Object**>(args[1]); | 591 Object** parameters = reinterpret_cast<Object**>(args[1]); |
562 CONVERT_SMI_ARG_CHECKED(argument_count, 2); | 592 CONVERT_SMI_ARG_CHECKED(argument_count, 2); |
563 #ifdef DEBUG | 593 #ifdef DEBUG |
564 // This runtime function does not materialize the correct arguments when the | 594 // This runtime function does not materialize the correct arguments when the |
565 // caller has been inlined, better make sure we are not hitting that case. | 595 // caller has been inlined, better make sure we are not hitting that case. |
566 List<JSFunction*> functions(1); | 596 List<JSFunction*> functions(1); |
567 JavaScriptFrameIterator it(isolate); | 597 JavaScriptFrameIterator it(isolate); |
568 it.frame()->GetFunctions(&functions); | 598 it.frame()->GetFunctions(&functions); |
569 DCHECK_EQ(1, functions.length()); | 599 DCHECK_EQ(1, functions.length()); |
570 #endif // DEBUG | 600 #endif // DEBUG |
571 return *NewStrictArguments(isolate, callee, parameters, argument_count); | 601 ParameterArguments argument_getter(parameters); |
602 return *NewStrictArguments(isolate, callee, argument_getter, argument_count); | |
572 } | 603 } |
573 | 604 |
574 | 605 |
575 RUNTIME_FUNCTION(Runtime_NewClosure) { | 606 RUNTIME_FUNCTION(Runtime_NewClosure) { |
576 HandleScope scope(isolate); | 607 HandleScope scope(isolate); |
577 DCHECK_EQ(1, args.length()); | 608 DCHECK_EQ(1, args.length()); |
578 CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0); | 609 CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0); |
579 Handle<Context> context(isolate->context(), isolate); | 610 Handle<Context> context(isolate->context(), isolate); |
580 return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context, | 611 return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context, |
581 NOT_TENURED); | 612 NOT_TENURED); |
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1134 | 1165 |
1135 // Lookup in the initial Object.prototype object. | 1166 // Lookup in the initial Object.prototype object. |
1136 Handle<Object> result; | 1167 Handle<Object> result; |
1137 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 1168 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
1138 isolate, result, | 1169 isolate, result, |
1139 Object::GetProperty(isolate->initial_object_prototype(), key)); | 1170 Object::GetProperty(isolate->initial_object_prototype(), key)); |
1140 return *result; | 1171 return *result; |
1141 } | 1172 } |
1142 } // namespace internal | 1173 } // namespace internal |
1143 } // namespace v8 | 1174 } // namespace v8 |
OLD | NEW |