 Chromium Code Reviews
 Chromium Code Reviews Issue 12385014:
  Hydrogen stubs for array constructors  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
    
  
    Issue 12385014:
  Hydrogen stubs for array constructors  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge| 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 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 125 parameters_[i] = param; | 125 parameters_[i] = param; | 
| 126 } | 126 } | 
| 127 | 127 | 
| 128 HInstruction* stack_parameter_count; | 128 HInstruction* stack_parameter_count; | 
| 129 if (descriptor_->stack_parameter_count_ != NULL) { | 129 if (descriptor_->stack_parameter_count_ != NULL) { | 
| 130 ASSERT(descriptor_->environment_length() == (param_count + 1)); | 130 ASSERT(descriptor_->environment_length() == (param_count + 1)); | 
| 131 stack_parameter_count = new(zone) HParameter(param_count, | 131 stack_parameter_count = new(zone) HParameter(param_count, | 
| 132 HParameter::REGISTER_PARAMETER, | 132 HParameter::REGISTER_PARAMETER, | 
| 133 Representation::Integer32()); | 133 Representation::Integer32()); | 
| 134 // it's essential to bind this value to the environment in case of deopt | 134 // it's essential to bind this value to the environment in case of deopt | 
| 135 AddInstruction(stack_parameter_count); | |
| 135 start_environment->Bind(param_count, stack_parameter_count); | 136 start_environment->Bind(param_count, stack_parameter_count); | 
| 136 AddInstruction(stack_parameter_count); | 137 arguments_length_ = AddInstruction(new(zone) HChange( | 
| 137 arguments_length_ = stack_parameter_count; | 138 stack_parameter_count, | 
| 139 Representation::Tagged(), | |
| 140 true, | |
| 141 false)); | |
| 138 } else { | 142 } else { | 
| 139 ASSERT(descriptor_->environment_length() == param_count); | 143 ASSERT(descriptor_->environment_length() == param_count); | 
| 140 stack_parameter_count = graph()->GetConstantMinus1(); | 144 stack_parameter_count = graph()->GetConstantMinus1(); | 
| 141 arguments_length_ = graph()->GetConstant0(); | 145 arguments_length_ = graph()->GetConstant0(); | 
| 142 } | 146 } | 
| 143 | 147 | 
| 144 context_ = new(zone) HContext(); | 148 context_ = new(zone) HContext(); | 
| 145 AddInstruction(context_); | 149 AddInstruction(context_); | 
| 146 start_environment->BindContext(context_); | 150 start_environment->BindContext(context_); | 
| 147 | 151 | 
| 148 AddSimulate(BailoutId::StubEntry()); | 152 AddSimulate(BailoutId::StubEntry()); | 
| 149 | 153 | 
| 150 NoObservableSideEffectsScope no_effects(this); | 154 NoObservableSideEffectsScope no_effects(this); | 
| 151 | 155 | 
| 152 HValue* return_value = BuildCodeStub(); | 156 HValue* return_value = BuildCodeStub(); | 
| 153 | 157 | 
| 154 // We might have extra expressions to pop from the stack in addition to the | 158 // We might have extra expressions to pop from the stack in addition to the | 
| 155 // arguments above | 159 // arguments above | 
| 156 HInstruction* stack_pop_count = stack_parameter_count; | 160 HInstruction* stack_pop_count = stack_parameter_count; | 
| 157 if (descriptor_->function_mode_ == JS_FUNCTION_STUB_MODE) { | 161 if (descriptor_->function_mode_ == JS_FUNCTION_STUB_MODE) { | 
| 158 HInstruction* amount = graph()->GetConstant1(); | 162 if (stack_parameter_count->IsParameter() && | 
| 159 stack_pop_count = AddInstruction( | 163 descriptor_->hint_stack_parameter_count_ < 0) { | 
| 160 HAdd::New(zone, context_, stack_parameter_count, amount)); | 164 HInstruction* amount = graph()->GetConstant1(); | 
| 161 stack_pop_count->ChangeRepresentation(Representation::Integer32()); | 165 stack_pop_count = AddInstruction( | 
| 162 stack_pop_count->ClearFlag(HValue::kCanOverflow); | 166 HAdd::New(zone, context_, stack_parameter_count, amount)); | 
| 167 stack_pop_count->ChangeRepresentation(Representation::Integer32()); | |
| 168 stack_pop_count->ClearFlag(HValue::kCanOverflow); | |
| 169 } else { | |
| 170 int count = descriptor_->hint_stack_parameter_count_; | |
| 171 if (count == 0) { | |
| 172 stack_pop_count = graph()->GetConstant0(); | |
| 173 } else if (count == 1) { | |
| 174 stack_pop_count = graph()->GetConstant1(); | |
| 175 } else { | |
| 176 stack_pop_count = AddInstruction(new(zone) | |
| 177 HConstant(count, Representation::Integer32())); | |
| 178 } | |
| 179 } | |
| 163 } | 180 } | 
| 164 | 181 | 
| 165 HReturn* hreturn_instruction = new(zone) HReturn(return_value, | 182 HReturn* hreturn_instruction = new(zone) HReturn(return_value, | 
| 166 context_, | 183 context_, | 
| 167 stack_pop_count); | 184 stack_pop_count); | 
| 168 current_block()->Finish(hreturn_instruction); | 185 current_block()->Finish(hreturn_instruction); | 
| 169 return true; | 186 return true; | 
| 170 } | 187 } | 
| 171 | 188 | 
| 172 | 189 | 
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 393 } | 410 } | 
| 394 | 411 | 
| 395 | 412 | 
| 396 Handle<Code> TransitionElementsKindStub::GenerateCode() { | 413 Handle<Code> TransitionElementsKindStub::GenerateCode() { | 
| 397 return DoGenerateCode(this); | 414 return DoGenerateCode(this); | 
| 398 } | 415 } | 
| 399 | 416 | 
| 400 | 417 | 
| 401 template <> | 418 template <> | 
| 402 HValue* CodeStubGraphBuilder<ArrayNoArgumentConstructorStub>::BuildCodeStub() { | 419 HValue* CodeStubGraphBuilder<ArrayNoArgumentConstructorStub>::BuildCodeStub() { | 
| 403 HInstruction* deopt = new(zone()) HSoftDeoptimize(); | 420 // ----------- S t a t e ------------- | 
| 404 AddInstruction(deopt); | 421 // -- Parameter 1 : type info cell | 
| 405 current_block()->MarkAsDeoptimizing(); | 422 // -- Parameter 0 : constructor | 
| 406 return GetParameter(0); | 423 // ----------------------------------- | 
| 424 // Get the right map | |
| 425 // Should be a constant | |
| 426 JSArrayBuilder array_builder(this, | |
| 427 casted_stub()->elements_kind(), | |
| 428 GetParameter(ArrayConstructorStubBase::kPropertyCell), | |
| 429 casted_stub()->mode()); | |
| 430 return array_builder.AllocateEmptyArray(); | |
| 407 } | 431 } | 
| 408 | 432 | 
| 409 | 433 | 
| 410 Handle<Code> ArrayNoArgumentConstructorStub::GenerateCode() { | 434 Handle<Code> ArrayNoArgumentConstructorStub::GenerateCode() { | 
| 411 return DoGenerateCode(this); | 435 return DoGenerateCode(this); | 
| 412 } | 436 } | 
| 413 | 437 | 
| 414 | 438 | 
| 415 template <> | 439 template <> | 
| 416 HValue* CodeStubGraphBuilder<ArraySingleArgumentConstructorStub>:: | 440 HValue* CodeStubGraphBuilder<ArraySingleArgumentConstructorStub>:: | 
| 417 BuildCodeStub() { | 441 BuildCodeStub() { | 
| 418 HInstruction* deopt = new(zone()) HSoftDeoptimize(); | 442 info()->MarkAsStubThatUsesArguments(); | 
| 419 AddInstruction(deopt); | 443 | 
| 420 current_block()->MarkAsDeoptimizing(); | 444 // Smi check and range check on the input arg. | 
| 421 return GetParameter(0); | 445 HValue* constant_one = graph()->GetConstant1(); | 
| 446 HValue* constant_zero = graph()->GetConstant0(); | |
| 447 | |
| 448 HInstruction* elements = AddInstruction( | |
| 449 new(zone()) HArgumentsElements(false)); | |
| 450 HInstruction* argument = AddInstruction( | |
| 451 new(zone()) HAccessArgumentsAt(elements, constant_one, constant_zero)); | |
| 452 | |
| 453 // AddInstruction(new(zone()) HCheckSmi(argument)); | |
| 
Hannes Payer (out of office)
2013/04/18 11:14:39
I think you can remove that line.
 
mvstanton
2013/04/18 13:39:26
thx!, done
 | |
| 454 | |
| 455 HConstant* max_alloc_length = | |
| 456 new(zone()) HConstant(JSObject::kInitialMaxFastElementArray, | |
| 457 Representation::Tagged()); | |
| 458 AddInstruction(max_alloc_length); | |
| 459 const int initial_capacity = JSArray::kPreallocatedArrayElements; | |
| 460 HConstant* initial_capacity_node = | |
| 461 new(zone()) HConstant(initial_capacity, Representation::Tagged()); | |
| 462 AddInstruction(initial_capacity_node); | |
| 463 | |
| 464 // Since we're forcing Integer32 representation for this HBoundsCheck, | |
| 465 // there's no need to Smi-check the index. | |
| 466 HBoundsCheck* checked_arg = AddBoundsCheck(argument, max_alloc_length, | |
| 467 ALLOW_SMI_KEY, | |
| 468 Representation::Tagged()); | |
| 469 IfBuilder if_builder(this); | |
| 470 if_builder.BeginIf(checked_arg, constant_zero, Token::EQ); | |
| 471 Push(initial_capacity_node); // capacity | |
| 472 Push(constant_zero); // length | |
| 473 if_builder.BeginElse(); | |
| 474 Push(checked_arg); // capacity | |
| 475 Push(checked_arg); // length | |
| 476 if_builder.End(); | |
| 477 | |
| 478 // Figure out total size | |
| 479 HValue* length = Pop(); | |
| 480 HValue* capacity = Pop(); | |
| 481 | |
| 482 // length->ChangeRepresentation(Representation::Integer32()); | |
| 483 // capacity->ChangeRepresentation(Representation::Integer32()); | |
| 484 | |
| 485 JSArrayBuilder array_builder(this, | |
| 486 casted_stub()->elements_kind(), | |
| 487 GetParameter(ArrayConstructorStubBase::kPropertyCell), | |
| 488 casted_stub()->mode()); | |
| 489 return array_builder.AllocateArray(capacity, length, true); | |
| 422 } | 490 } | 
| 423 | 491 | 
| 424 | 492 | 
| 425 Handle<Code> ArraySingleArgumentConstructorStub::GenerateCode() { | 493 Handle<Code> ArraySingleArgumentConstructorStub::GenerateCode() { | 
| 426 return DoGenerateCode(this); | 494 return DoGenerateCode(this); | 
| 427 } | 495 } | 
| 428 | 496 | 
| 429 | 497 | 
| 430 template <> | 498 template <> | 
| 431 HValue* CodeStubGraphBuilder<ArrayNArgumentsConstructorStub>::BuildCodeStub() { | 499 HValue* CodeStubGraphBuilder<ArrayNArgumentsConstructorStub>::BuildCodeStub() { | 
| 432 HInstruction* deopt = new(zone()) HSoftDeoptimize(); | 500 info()->MarkAsStubThatUsesArguments(); | 
| 433 AddInstruction(deopt); | 501 ElementsKind kind = casted_stub()->elements_kind(); | 
| 434 current_block()->MarkAsDeoptimizing(); | 502 HValue* length = GetArgumentsLength(); | 
| 435 return GetParameter(0); | 503 | 
| 504 JSArrayBuilder array_builder(this, | |
| 505 kind, | |
| 506 GetParameter(ArrayConstructorStubBase::kPropertyCell), | |
| 507 casted_stub()->mode()); | |
| 508 | |
| 509 // We need to fill with the hole if it's a smi array in the multi-argument | |
| 510 // case because we might have to bail out while copying arguments into | |
| 511 // the array because they aren't compatible with a smi array. | |
| 512 // If it's a double array, no problem, and if it's fast then no | |
| 513 // problem either because doubles are boxed. | |
| 514 bool fill_with_hole = IsFastSmiElementsKind(kind); | |
| 515 HValue* new_object = array_builder.AllocateArray(length, | |
| 516 length, | |
| 517 fill_with_hole); | |
| 518 HValue* elements = array_builder.GetElementsLocation(); | |
| 519 ASSERT(elements != NULL); | |
| 520 | |
| 521 // Now populate the elements correctly. | |
| 522 LoopBuilder builder(this, | |
| 523 context(), | |
| 524 LoopBuilder::kPostIncrement); | |
| 525 HValue* start = graph()->GetConstant0(); | |
| 526 HValue* key = builder.BeginBody(start, length, Token::LT); | |
| 527 HInstruction* argument_elements = AddInstruction( | |
| 528 new(zone()) HArgumentsElements(false)); | |
| 529 HInstruction* argument = AddInstruction(new(zone()) HAccessArgumentsAt( | |
| 530 argument_elements, length, key)); | |
| 531 | |
| 532 // Checks to prevent incompatible stores | |
| 533 if (IsFastSmiElementsKind(kind)) { | |
| 534 AddInstruction(new(zone()) HCheckSmi(argument)); | |
| 535 } | |
| 536 | |
| 537 AddInstruction(new(zone()) HStoreKeyed(elements, key, argument, kind)); | |
| 538 builder.EndBody(); | |
| 539 return new_object; | |
| 436 } | 540 } | 
| 437 | 541 | 
| 438 | 542 | 
| 439 Handle<Code> ArrayNArgumentsConstructorStub::GenerateCode() { | 543 Handle<Code> ArrayNArgumentsConstructorStub::GenerateCode() { | 
| 440 return DoGenerateCode(this); | 544 return DoGenerateCode(this); | 
| 441 } | 545 } | 
| 442 | 546 | 
| 443 } } // namespace v8::internal | 547 } } // namespace v8::internal | 
| OLD | NEW |