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