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