OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 parameters_[i] = param; | 123 parameters_[i] = param; |
124 } | 124 } |
125 | 125 |
126 HInstruction* stack_parameter_count; | 126 HInstruction* stack_parameter_count; |
127 if (descriptor_->stack_parameter_count_ != NULL) { | 127 if (descriptor_->stack_parameter_count_ != NULL) { |
128 ASSERT(descriptor_->environment_length() == (param_count + 1)); | 128 ASSERT(descriptor_->environment_length() == (param_count + 1)); |
129 stack_parameter_count = new(zone) HParameter(param_count, | 129 stack_parameter_count = new(zone) HParameter(param_count, |
130 HParameter::REGISTER_PARAMETER, | 130 HParameter::REGISTER_PARAMETER, |
131 Representation::Integer32()); | 131 Representation::Integer32()); |
132 // it's essential to bind this value to the environment in case of deopt | 132 // it's essential to bind this value to the environment in case of deopt |
| 133 AddInstruction(stack_parameter_count); |
133 start_environment->Bind(param_count, stack_parameter_count); | 134 start_environment->Bind(param_count, stack_parameter_count); |
134 AddInstruction(stack_parameter_count); | 135 arguments_length_ = AddInstruction(new(zone) HChange( |
135 arguments_length_ = stack_parameter_count; | 136 stack_parameter_count, |
| 137 Representation::Tagged(), |
| 138 true, |
| 139 false)); |
136 } else { | 140 } else { |
137 ASSERT(descriptor_->environment_length() == param_count); | 141 ASSERT(descriptor_->environment_length() == param_count); |
138 stack_parameter_count = graph()->GetConstantMinus1(); | 142 stack_parameter_count = graph()->GetConstantMinus1(); |
139 arguments_length_ = graph()->GetConstant0(); | 143 arguments_length_ = graph()->GetConstant0(); |
140 } | 144 } |
141 | 145 |
142 context_ = new(zone) HContext(); | 146 context_ = new(zone) HContext(); |
143 AddInstruction(context_); | 147 AddInstruction(context_); |
144 start_environment->BindContext(context_); | 148 start_environment->BindContext(context_); |
145 | 149 |
146 AddSimulate(BailoutId::StubEntry()); | 150 AddSimulate(BailoutId::StubEntry()); |
147 | 151 |
148 NoObservableSideEffectsScope no_effects(this); | 152 NoObservableSideEffectsScope no_effects(this); |
149 | 153 |
150 HValue* return_value = BuildCodeStub(); | 154 HValue* return_value = BuildCodeStub(); |
151 | 155 |
152 // We might have extra expressions to pop from the stack in addition to the | 156 // We might have extra expressions to pop from the stack in addition to the |
153 // arguments above | 157 // arguments above |
154 HInstruction* stack_pop_count = stack_parameter_count; | 158 HInstruction* stack_pop_count = stack_parameter_count; |
155 if (descriptor_->function_mode_ == JS_FUNCTION_STUB_MODE) { | 159 if (descriptor_->function_mode_ == JS_FUNCTION_STUB_MODE) { |
156 HInstruction* amount = graph()->GetConstant1(); | 160 if (!stack_parameter_count->IsConstant() && |
157 stack_pop_count = AddInstruction( | 161 descriptor_->hint_stack_parameter_count_ < 0) { |
158 HAdd::New(zone, context_, stack_parameter_count, amount)); | 162 HInstruction* amount = graph()->GetConstant1(); |
159 stack_pop_count->ChangeRepresentation(Representation::Integer32()); | 163 stack_pop_count = AddInstruction( |
160 stack_pop_count->ClearFlag(HValue::kCanOverflow); | 164 HAdd::New(zone, context_, stack_parameter_count, amount)); |
| 165 stack_pop_count->ChangeRepresentation(Representation::Integer32()); |
| 166 stack_pop_count->ClearFlag(HValue::kCanOverflow); |
| 167 } else { |
| 168 int count = descriptor_->hint_stack_parameter_count_; |
| 169 stack_pop_count = AddInstruction(new(zone) |
| 170 HConstant(count, Representation::Integer32())); |
| 171 } |
161 } | 172 } |
162 | 173 |
163 HReturn* hreturn_instruction = new(zone) HReturn(return_value, | 174 HReturn* hreturn_instruction = new(zone) HReturn(return_value, |
164 context_, | 175 context_, |
165 stack_pop_count); | 176 stack_pop_count); |
166 current_block()->Finish(hreturn_instruction); | 177 current_block()->Finish(hreturn_instruction); |
167 return true; | 178 return true; |
168 } | 179 } |
169 | 180 |
170 | 181 |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
470 } | 481 } |
471 | 482 |
472 | 483 |
473 Handle<Code> TransitionElementsKindStub::GenerateCode() { | 484 Handle<Code> TransitionElementsKindStub::GenerateCode() { |
474 return DoGenerateCode(this); | 485 return DoGenerateCode(this); |
475 } | 486 } |
476 | 487 |
477 | 488 |
478 template <> | 489 template <> |
479 HValue* CodeStubGraphBuilder<ArrayNoArgumentConstructorStub>::BuildCodeStub() { | 490 HValue* CodeStubGraphBuilder<ArrayNoArgumentConstructorStub>::BuildCodeStub() { |
480 HInstruction* deopt = new(zone()) HSoftDeoptimize(); | 491 // ----------- S t a t e ------------- |
481 AddInstruction(deopt); | 492 // -- Parameter 1 : type info cell |
482 current_block()->MarkAsDeoptimizing(); | 493 // -- Parameter 0 : constructor |
483 return GetParameter(0); | 494 // ----------------------------------- |
| 495 // Get the right map |
| 496 // Should be a constant |
| 497 JSArrayBuilder array_builder( |
| 498 this, |
| 499 casted_stub()->elements_kind(), |
| 500 GetParameter(ArrayConstructorStubBase::kPropertyCell), |
| 501 casted_stub()->mode()); |
| 502 return array_builder.AllocateEmptyArray(); |
484 } | 503 } |
485 | 504 |
486 | 505 |
487 Handle<Code> ArrayNoArgumentConstructorStub::GenerateCode() { | 506 Handle<Code> ArrayNoArgumentConstructorStub::GenerateCode() { |
488 return DoGenerateCode(this); | 507 return DoGenerateCode(this); |
489 } | 508 } |
490 | 509 |
491 | 510 |
492 template <> | 511 template <> |
493 HValue* CodeStubGraphBuilder<ArraySingleArgumentConstructorStub>:: | 512 HValue* CodeStubGraphBuilder<ArraySingleArgumentConstructorStub>:: |
494 BuildCodeStub() { | 513 BuildCodeStub() { |
495 HInstruction* deopt = new(zone()) HSoftDeoptimize(); | 514 // Smi check and range check on the input arg. |
496 AddInstruction(deopt); | 515 HValue* constant_one = graph()->GetConstant1(); |
497 current_block()->MarkAsDeoptimizing(); | 516 HValue* constant_zero = graph()->GetConstant0(); |
498 return GetParameter(0); | 517 |
| 518 HInstruction* elements = AddInstruction( |
| 519 new(zone()) HArgumentsElements(false)); |
| 520 HInstruction* argument = AddInstruction( |
| 521 new(zone()) HAccessArgumentsAt(elements, constant_one, constant_zero)); |
| 522 |
| 523 HConstant* max_alloc_length = |
| 524 new(zone()) HConstant(JSObject::kInitialMaxFastElementArray, |
| 525 Representation::Tagged()); |
| 526 AddInstruction(max_alloc_length); |
| 527 const int initial_capacity = JSArray::kPreallocatedArrayElements; |
| 528 HConstant* initial_capacity_node = |
| 529 new(zone()) HConstant(initial_capacity, Representation::Tagged()); |
| 530 AddInstruction(initial_capacity_node); |
| 531 |
| 532 // Since we're forcing Integer32 representation for this HBoundsCheck, |
| 533 // there's no need to Smi-check the index. |
| 534 HBoundsCheck* checked_arg = AddBoundsCheck(argument, max_alloc_length, |
| 535 ALLOW_SMI_KEY, |
| 536 Representation::Tagged()); |
| 537 IfBuilder if_builder(this); |
| 538 if_builder.IfCompare(checked_arg, constant_zero, Token::EQ); |
| 539 if_builder.Then(); |
| 540 Push(initial_capacity_node); // capacity |
| 541 Push(constant_zero); // length |
| 542 if_builder.Else(); |
| 543 Push(checked_arg); // capacity |
| 544 Push(checked_arg); // length |
| 545 if_builder.End(); |
| 546 |
| 547 // Figure out total size |
| 548 HValue* length = Pop(); |
| 549 HValue* capacity = Pop(); |
| 550 |
| 551 JSArrayBuilder array_builder( |
| 552 this, |
| 553 casted_stub()->elements_kind(), |
| 554 GetParameter(ArrayConstructorStubBase::kPropertyCell), |
| 555 casted_stub()->mode()); |
| 556 return array_builder.AllocateArray(capacity, length, true); |
499 } | 557 } |
500 | 558 |
501 | 559 |
502 Handle<Code> ArraySingleArgumentConstructorStub::GenerateCode() { | 560 Handle<Code> ArraySingleArgumentConstructorStub::GenerateCode() { |
503 return DoGenerateCode(this); | 561 return DoGenerateCode(this); |
504 } | 562 } |
505 | 563 |
506 | 564 |
507 template <> | 565 template <> |
508 HValue* CodeStubGraphBuilder<ArrayNArgumentsConstructorStub>::BuildCodeStub() { | 566 HValue* CodeStubGraphBuilder<ArrayNArgumentsConstructorStub>::BuildCodeStub() { |
509 HInstruction* deopt = new(zone()) HSoftDeoptimize(); | 567 ElementsKind kind = casted_stub()->elements_kind(); |
510 AddInstruction(deopt); | 568 HValue* length = GetArgumentsLength(); |
511 current_block()->MarkAsDeoptimizing(); | 569 |
512 return GetParameter(0); | 570 JSArrayBuilder array_builder( |
| 571 this, |
| 572 kind, |
| 573 GetParameter(ArrayConstructorStubBase::kPropertyCell), |
| 574 casted_stub()->mode()); |
| 575 |
| 576 // We need to fill with the hole if it's a smi array in the multi-argument |
| 577 // case because we might have to bail out while copying arguments into |
| 578 // the array because they aren't compatible with a smi array. |
| 579 // If it's a double array, no problem, and if it's fast then no |
| 580 // problem either because doubles are boxed. |
| 581 bool fill_with_hole = IsFastSmiElementsKind(kind); |
| 582 HValue* new_object = array_builder.AllocateArray(length, |
| 583 length, |
| 584 fill_with_hole); |
| 585 HValue* elements = array_builder.GetElementsLocation(); |
| 586 ASSERT(elements != NULL); |
| 587 |
| 588 // Now populate the elements correctly. |
| 589 LoopBuilder builder(this, |
| 590 context(), |
| 591 LoopBuilder::kPostIncrement); |
| 592 HValue* start = graph()->GetConstant0(); |
| 593 HValue* key = builder.BeginBody(start, length, Token::LT); |
| 594 HInstruction* argument_elements = AddInstruction( |
| 595 new(zone()) HArgumentsElements(false)); |
| 596 HInstruction* argument = AddInstruction(new(zone()) HAccessArgumentsAt( |
| 597 argument_elements, length, key)); |
| 598 |
| 599 // Checks to prevent incompatible stores |
| 600 if (IsFastSmiElementsKind(kind)) { |
| 601 AddInstruction(new(zone()) HCheckSmi(argument)); |
| 602 } |
| 603 |
| 604 AddInstruction(new(zone()) HStoreKeyed(elements, key, argument, kind)); |
| 605 builder.EndBody(); |
| 606 return new_object; |
513 } | 607 } |
514 | 608 |
515 | 609 |
516 Handle<Code> ArrayNArgumentsConstructorStub::GenerateCode() { | 610 Handle<Code> ArrayNArgumentsConstructorStub::GenerateCode() { |
517 return DoGenerateCode(this); | 611 return DoGenerateCode(this); |
518 } | 612 } |
519 | 613 |
520 } } // namespace v8::internal | 614 } } // namespace v8::internal |
OLD | NEW |