| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
| 8 #include "src/field-index.h" | 8 #include "src/field-index.h" |
| 9 #include "src/hydrogen.h" | 9 #include "src/hydrogen.h" |
| 10 #include "src/lithium.h" | 10 #include "src/lithium.h" |
| 11 | 11 |
| 12 namespace v8 { | 12 namespace v8 { |
| 13 namespace internal { | 13 namespace internal { |
| 14 | 14 |
| 15 | 15 |
| 16 static LChunk* OptimizeGraph(HGraph* graph) { | 16 static LChunk* OptimizeGraph(HGraph* graph) { |
| 17 DisallowHeapAllocation no_allocation; | 17 DisallowHeapAllocation no_allocation; |
| 18 DisallowHandleAllocation no_handles; | 18 DisallowHandleAllocation no_handles; |
| 19 DisallowHandleDereference no_deref; | 19 DisallowHandleDereference no_deref; |
| 20 | 20 |
| 21 ASSERT(graph != NULL); | 21 DCHECK(graph != NULL); |
| 22 BailoutReason bailout_reason = kNoReason; | 22 BailoutReason bailout_reason = kNoReason; |
| 23 if (!graph->Optimize(&bailout_reason)) { | 23 if (!graph->Optimize(&bailout_reason)) { |
| 24 FATAL(GetBailoutReason(bailout_reason)); | 24 FATAL(GetBailoutReason(bailout_reason)); |
| 25 } | 25 } |
| 26 LChunk* chunk = LChunk::NewChunk(graph); | 26 LChunk* chunk = LChunk::NewChunk(graph); |
| 27 if (chunk == NULL) { | 27 if (chunk == NULL) { |
| 28 FATAL(GetBailoutReason(graph->info()->bailout_reason())); | 28 FATAL(GetBailoutReason(graph->info()->bailout_reason())); |
| 29 } | 29 } |
| 30 return chunk; | 30 return chunk; |
| 31 } | 31 } |
| 32 | 32 |
| 33 | 33 |
| 34 class CodeStubGraphBuilderBase : public HGraphBuilder { | 34 class CodeStubGraphBuilderBase : public HGraphBuilder { |
| 35 public: | 35 public: |
| 36 CodeStubGraphBuilderBase(Isolate* isolate, HydrogenCodeStub* stub) | 36 CodeStubGraphBuilderBase(Isolate* isolate, HydrogenCodeStub* stub) |
| 37 : HGraphBuilder(&info_), | 37 : HGraphBuilder(&info_), |
| 38 arguments_length_(NULL), | 38 arguments_length_(NULL), |
| 39 info_(stub, isolate), | 39 info_(stub, isolate), |
| 40 context_(NULL) { | 40 context_(NULL) { |
| 41 descriptor_ = stub->GetInterfaceDescriptor(); | 41 descriptor_ = stub->GetInterfaceDescriptor(); |
| 42 int parameter_count = descriptor_->GetEnvironmentParameterCount(); | 42 int parameter_count = descriptor_->GetEnvironmentParameterCount(); |
| 43 parameters_.Reset(new HParameter*[parameter_count]); | 43 parameters_.Reset(new HParameter*[parameter_count]); |
| 44 } | 44 } |
| 45 virtual bool BuildGraph(); | 45 virtual bool BuildGraph(); |
| 46 | 46 |
| 47 protected: | 47 protected: |
| 48 virtual HValue* BuildCodeStub() = 0; | 48 virtual HValue* BuildCodeStub() = 0; |
| 49 HParameter* GetParameter(int parameter) { | 49 HParameter* GetParameter(int parameter) { |
| 50 ASSERT(parameter < descriptor_->GetEnvironmentParameterCount()); | 50 DCHECK(parameter < descriptor_->GetEnvironmentParameterCount()); |
| 51 return parameters_[parameter]; | 51 return parameters_[parameter]; |
| 52 } | 52 } |
| 53 HValue* GetArgumentsLength() { | 53 HValue* GetArgumentsLength() { |
| 54 // This is initialized in BuildGraph() | 54 // This is initialized in BuildGraph() |
| 55 ASSERT(arguments_length_ != NULL); | 55 DCHECK(arguments_length_ != NULL); |
| 56 return arguments_length_; | 56 return arguments_length_; |
| 57 } | 57 } |
| 58 CompilationInfo* info() { return &info_; } | 58 CompilationInfo* info() { return &info_; } |
| 59 HydrogenCodeStub* stub() { return info_.code_stub(); } | 59 HydrogenCodeStub* stub() { return info_.code_stub(); } |
| 60 HContext* context() { return context_; } | 60 HContext* context() { return context_; } |
| 61 Isolate* isolate() { return info_.isolate(); } | 61 Isolate* isolate() { return info_.isolate(); } |
| 62 | 62 |
| 63 HLoadNamedField* BuildLoadNamedField(HValue* object, | 63 HLoadNamedField* BuildLoadNamedField(HValue* object, |
| 64 FieldIndex index); | 64 FieldIndex index); |
| 65 | 65 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 HParameter::REGISTER_PARAMETER, r); | 132 HParameter::REGISTER_PARAMETER, r); |
| 133 start_environment->Bind(i, param); | 133 start_environment->Bind(i, param); |
| 134 parameters_[i] = param; | 134 parameters_[i] = param; |
| 135 if (descriptor_->IsEnvironmentParameterCountRegister(i)) { | 135 if (descriptor_->IsEnvironmentParameterCountRegister(i)) { |
| 136 param->set_type(HType::Smi()); | 136 param->set_type(HType::Smi()); |
| 137 stack_parameter_count = param; | 137 stack_parameter_count = param; |
| 138 arguments_length_ = stack_parameter_count; | 138 arguments_length_ = stack_parameter_count; |
| 139 } | 139 } |
| 140 } | 140 } |
| 141 | 141 |
| 142 ASSERT(!runtime_stack_params || arguments_length_ != NULL); | 142 DCHECK(!runtime_stack_params || arguments_length_ != NULL); |
| 143 if (!runtime_stack_params) { | 143 if (!runtime_stack_params) { |
| 144 stack_parameter_count = graph()->GetConstantMinus1(); | 144 stack_parameter_count = graph()->GetConstantMinus1(); |
| 145 arguments_length_ = graph()->GetConstant0(); | 145 arguments_length_ = graph()->GetConstant0(); |
| 146 } | 146 } |
| 147 | 147 |
| 148 context_ = Add<HContext>(); | 148 context_ = Add<HContext>(); |
| 149 start_environment->BindContext(context_); | 149 start_environment->BindContext(context_); |
| 150 | 150 |
| 151 Add<HSimulate>(BailoutId::StubEntry()); | 151 Add<HSimulate>(BailoutId::StubEntry()); |
| 152 | 152 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 CodeStubInterfaceDescriptor* descriptor = | 254 CodeStubInterfaceDescriptor* descriptor = |
| 255 isolate->code_stub_interface_descriptor(major_key); | 255 isolate->code_stub_interface_descriptor(major_key); |
| 256 if (!descriptor->IsInitialized()) { | 256 if (!descriptor->IsInitialized()) { |
| 257 stub->InitializeInterfaceDescriptor(descriptor); | 257 stub->InitializeInterfaceDescriptor(descriptor); |
| 258 } | 258 } |
| 259 | 259 |
| 260 // If we are uninitialized we can use a light-weight stub to enter | 260 // If we are uninitialized we can use a light-weight stub to enter |
| 261 // the runtime that is significantly faster than using the standard | 261 // the runtime that is significantly faster than using the standard |
| 262 // stub-failure deopt mechanism. | 262 // stub-failure deopt mechanism. |
| 263 if (stub->IsUninitialized() && descriptor->has_miss_handler()) { | 263 if (stub->IsUninitialized() && descriptor->has_miss_handler()) { |
| 264 ASSERT(!descriptor->stack_parameter_count().is_valid()); | 264 DCHECK(!descriptor->stack_parameter_count().is_valid()); |
| 265 return stub->GenerateLightweightMissCode(); | 265 return stub->GenerateLightweightMissCode(); |
| 266 } | 266 } |
| 267 base::ElapsedTimer timer; | 267 base::ElapsedTimer timer; |
| 268 if (FLAG_profile_hydrogen_code_stub_compilation) { | 268 if (FLAG_profile_hydrogen_code_stub_compilation) { |
| 269 timer.Start(); | 269 timer.Start(); |
| 270 } | 270 } |
| 271 CodeStubGraphBuilder<Stub> builder(isolate, stub); | 271 CodeStubGraphBuilder<Stub> builder(isolate, stub); |
| 272 LChunk* chunk = OptimizeGraph(builder.CreateGraph()); | 272 LChunk* chunk = OptimizeGraph(builder.CreateGraph()); |
| 273 // TODO(yangguo) remove this once the code serializer handles code stubs. | 273 // TODO(yangguo) remove this once the code serializer handles code stubs. |
| 274 if (FLAG_serialize_toplevel) chunk->info()->PrepareForSerializing(); | 274 if (FLAG_serialize_toplevel) chunk->info()->PrepareForSerializing(); |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 437 HInstruction* object = Add<HAllocate>(size_in_bytes, HType::JSObject(), | 437 HInstruction* object = Add<HAllocate>(size_in_bytes, HType::JSObject(), |
| 438 NOT_TENURED, JS_OBJECT_TYPE); | 438 NOT_TENURED, JS_OBJECT_TYPE); |
| 439 | 439 |
| 440 for (int i = 0; i < object_size; i += kPointerSize) { | 440 for (int i = 0; i < object_size; i += kPointerSize) { |
| 441 HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(i); | 441 HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(i); |
| 442 Add<HStoreNamedField>( | 442 Add<HStoreNamedField>( |
| 443 object, access, Add<HLoadNamedField>( | 443 object, access, Add<HLoadNamedField>( |
| 444 boilerplate, static_cast<HValue*>(NULL), access)); | 444 boilerplate, static_cast<HValue*>(NULL), access)); |
| 445 } | 445 } |
| 446 | 446 |
| 447 ASSERT(FLAG_allocation_site_pretenuring || (size == object_size)); | 447 DCHECK(FLAG_allocation_site_pretenuring || (size == object_size)); |
| 448 if (FLAG_allocation_site_pretenuring) { | 448 if (FLAG_allocation_site_pretenuring) { |
| 449 BuildCreateAllocationMemento( | 449 BuildCreateAllocationMemento( |
| 450 object, Add<HConstant>(object_size), allocation_site); | 450 object, Add<HConstant>(object_size), allocation_site); |
| 451 } | 451 } |
| 452 | 452 |
| 453 environment()->Push(object); | 453 environment()->Push(object); |
| 454 checker.ElseDeopt("Uninitialized boilerplate in fast clone"); | 454 checker.ElseDeopt("Uninitialized boilerplate in fast clone"); |
| 455 checker.End(); | 455 checker.End(); |
| 456 | 456 |
| 457 return environment()->Pop(); | 457 return environment()->Pop(); |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 727 // TODO(mvstanton): consider an instruction to memset fill the array | 727 // TODO(mvstanton): consider an instruction to memset fill the array |
| 728 // with zero in this case instead. | 728 // with zero in this case instead. |
| 729 JSArrayBuilder::FillMode fill_mode = IsFastSmiElementsKind(kind) | 729 JSArrayBuilder::FillMode fill_mode = IsFastSmiElementsKind(kind) |
| 730 ? JSArrayBuilder::FILL_WITH_HOLE | 730 ? JSArrayBuilder::FILL_WITH_HOLE |
| 731 : JSArrayBuilder::DONT_FILL_WITH_HOLE; | 731 : JSArrayBuilder::DONT_FILL_WITH_HOLE; |
| 732 HValue* new_object = array_builder->AllocateArray(checked_length, | 732 HValue* new_object = array_builder->AllocateArray(checked_length, |
| 733 max_alloc_length, | 733 max_alloc_length, |
| 734 checked_length, | 734 checked_length, |
| 735 fill_mode); | 735 fill_mode); |
| 736 HValue* elements = array_builder->GetElementsLocation(); | 736 HValue* elements = array_builder->GetElementsLocation(); |
| 737 ASSERT(elements != NULL); | 737 DCHECK(elements != NULL); |
| 738 | 738 |
| 739 // Now populate the elements correctly. | 739 // Now populate the elements correctly. |
| 740 LoopBuilder builder(this, | 740 LoopBuilder builder(this, |
| 741 context(), | 741 context(), |
| 742 LoopBuilder::kPostIncrement); | 742 LoopBuilder::kPostIncrement); |
| 743 HValue* start = graph()->GetConstant0(); | 743 HValue* start = graph()->GetConstant0(); |
| 744 HValue* key = builder.BeginBody(start, checked_length, Token::LT); | 744 HValue* key = builder.BeginBody(start, checked_length, Token::LT); |
| 745 HInstruction* argument_elements = Add<HArgumentsElements>(false); | 745 HInstruction* argument_elements = Add<HArgumentsElements>(false); |
| 746 HInstruction* argument = Add<HAccessArgumentsAt>( | 746 HInstruction* argument = Add<HAccessArgumentsAt>( |
| 747 argument_elements, checked_length, key); | 747 argument_elements, checked_length, key); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 861 HValue* CodeStubGraphBuilder<BinaryOpICStub>::BuildCodeInitializedStub() { | 861 HValue* CodeStubGraphBuilder<BinaryOpICStub>::BuildCodeInitializedStub() { |
| 862 BinaryOpIC::State state = casted_stub()->state(); | 862 BinaryOpIC::State state = casted_stub()->state(); |
| 863 | 863 |
| 864 HValue* left = GetParameter(BinaryOpICStub::kLeft); | 864 HValue* left = GetParameter(BinaryOpICStub::kLeft); |
| 865 HValue* right = GetParameter(BinaryOpICStub::kRight); | 865 HValue* right = GetParameter(BinaryOpICStub::kRight); |
| 866 | 866 |
| 867 Type* left_type = state.GetLeftType(zone()); | 867 Type* left_type = state.GetLeftType(zone()); |
| 868 Type* right_type = state.GetRightType(zone()); | 868 Type* right_type = state.GetRightType(zone()); |
| 869 Type* result_type = state.GetResultType(zone()); | 869 Type* result_type = state.GetResultType(zone()); |
| 870 | 870 |
| 871 ASSERT(!left_type->Is(Type::None()) && !right_type->Is(Type::None()) && | 871 DCHECK(!left_type->Is(Type::None()) && !right_type->Is(Type::None()) && |
| 872 (state.HasSideEffects() || !result_type->Is(Type::None()))); | 872 (state.HasSideEffects() || !result_type->Is(Type::None()))); |
| 873 | 873 |
| 874 HValue* result = NULL; | 874 HValue* result = NULL; |
| 875 HAllocationMode allocation_mode(NOT_TENURED); | 875 HAllocationMode allocation_mode(NOT_TENURED); |
| 876 if (state.op() == Token::ADD && | 876 if (state.op() == Token::ADD && |
| 877 (left_type->Maybe(Type::String()) || right_type->Maybe(Type::String())) && | 877 (left_type->Maybe(Type::String()) || right_type->Maybe(Type::String())) && |
| 878 !left_type->Is(Type::String()) && !right_type->Is(Type::String())) { | 878 !left_type->Is(Type::String()) && !right_type->Is(Type::String())) { |
| 879 // For the generic add stub a fast case for string addition is performance | 879 // For the generic add stub a fast case for string addition is performance |
| 880 // critical. | 880 // critical. |
| 881 if (left_type->Maybe(Type::String())) { | 881 if (left_type->Maybe(Type::String())) { |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1171 Add<HStoreCodeEntry>(js_function, code_object); | 1171 Add<HStoreCodeEntry>(js_function, code_object); |
| 1172 } | 1172 } |
| 1173 | 1173 |
| 1174 | 1174 |
| 1175 HInstruction* CodeStubGraphBuilderBase::LoadFromOptimizedCodeMap( | 1175 HInstruction* CodeStubGraphBuilderBase::LoadFromOptimizedCodeMap( |
| 1176 HValue* optimized_map, | 1176 HValue* optimized_map, |
| 1177 HValue* iterator, | 1177 HValue* iterator, |
| 1178 int field_offset) { | 1178 int field_offset) { |
| 1179 // By making sure to express these loads in the form [<hvalue> + constant] | 1179 // By making sure to express these loads in the form [<hvalue> + constant] |
| 1180 // the keyed load can be hoisted. | 1180 // the keyed load can be hoisted. |
| 1181 ASSERT(field_offset >= 0 && field_offset < SharedFunctionInfo::kEntryLength); | 1181 DCHECK(field_offset >= 0 && field_offset < SharedFunctionInfo::kEntryLength); |
| 1182 HValue* field_slot = iterator; | 1182 HValue* field_slot = iterator; |
| 1183 if (field_offset > 0) { | 1183 if (field_offset > 0) { |
| 1184 HValue* field_offset_value = Add<HConstant>(field_offset); | 1184 HValue* field_offset_value = Add<HConstant>(field_offset); |
| 1185 field_slot = AddUncasted<HAdd>(iterator, field_offset_value); | 1185 field_slot = AddUncasted<HAdd>(iterator, field_offset_value); |
| 1186 } | 1186 } |
| 1187 HInstruction* field_entry = Add<HLoadKeyed>(optimized_map, field_slot, | 1187 HInstruction* field_entry = Add<HLoadKeyed>(optimized_map, field_slot, |
| 1188 static_cast<HValue*>(NULL), FAST_ELEMENTS); | 1188 static_cast<HValue*>(NULL), FAST_ELEMENTS); |
| 1189 return field_entry; | 1189 return field_entry; |
| 1190 } | 1190 } |
| 1191 | 1191 |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1458 static_cast<int>(Map::ElementsKindBits::encode(next_kind))); | 1458 static_cast<int>(Map::ElementsKindBits::encode(next_kind))); |
| 1459 | 1459 |
| 1460 if_builder->If<HCompareNumericAndBranch>(bit_field2, kind_limit, Token::LT); | 1460 if_builder->If<HCompareNumericAndBranch>(bit_field2, kind_limit, Token::LT); |
| 1461 if_builder->Then(); | 1461 if_builder->Then(); |
| 1462 } | 1462 } |
| 1463 | 1463 |
| 1464 | 1464 |
| 1465 void CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildFastElementLoad( | 1465 void CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildFastElementLoad( |
| 1466 HGraphBuilder::IfBuilder* if_builder, HValue* receiver, HValue* key, | 1466 HGraphBuilder::IfBuilder* if_builder, HValue* receiver, HValue* key, |
| 1467 HValue* instance_type, HValue* bit_field2, ElementsKind kind) { | 1467 HValue* instance_type, HValue* bit_field2, ElementsKind kind) { |
| 1468 ASSERT(!IsExternalArrayElementsKind(kind)); | 1468 DCHECK(!IsExternalArrayElementsKind(kind)); |
| 1469 | 1469 |
| 1470 BuildElementsKindLimitCheck(if_builder, bit_field2, kind); | 1470 BuildElementsKindLimitCheck(if_builder, bit_field2, kind); |
| 1471 | 1471 |
| 1472 IfBuilder js_array_check(this); | 1472 IfBuilder js_array_check(this); |
| 1473 js_array_check.If<HCompareNumericAndBranch>( | 1473 js_array_check.If<HCompareNumericAndBranch>( |
| 1474 instance_type, Add<HConstant>(JS_ARRAY_TYPE), Token::EQ); | 1474 instance_type, Add<HConstant>(JS_ARRAY_TYPE), Token::EQ); |
| 1475 js_array_check.Then(); | 1475 js_array_check.Then(); |
| 1476 Push(BuildUncheckedMonomorphicElementAccess(receiver, key, NULL, | 1476 Push(BuildUncheckedMonomorphicElementAccess(receiver, key, NULL, |
| 1477 true, kind, | 1477 true, kind, |
| 1478 LOAD, NEVER_RETURN_HOLE, | 1478 LOAD, NEVER_RETURN_HOLE, |
| 1479 STANDARD_STORE)); | 1479 STANDARD_STORE)); |
| 1480 js_array_check.Else(); | 1480 js_array_check.Else(); |
| 1481 Push(BuildUncheckedMonomorphicElementAccess(receiver, key, NULL, | 1481 Push(BuildUncheckedMonomorphicElementAccess(receiver, key, NULL, |
| 1482 false, kind, | 1482 false, kind, |
| 1483 LOAD, NEVER_RETURN_HOLE, | 1483 LOAD, NEVER_RETURN_HOLE, |
| 1484 STANDARD_STORE)); | 1484 STANDARD_STORE)); |
| 1485 js_array_check.End(); | 1485 js_array_check.End(); |
| 1486 } | 1486 } |
| 1487 | 1487 |
| 1488 | 1488 |
| 1489 void CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildExternalElementLoad( | 1489 void CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildExternalElementLoad( |
| 1490 HGraphBuilder::IfBuilder* if_builder, HValue* receiver, HValue* key, | 1490 HGraphBuilder::IfBuilder* if_builder, HValue* receiver, HValue* key, |
| 1491 HValue* instance_type, HValue* bit_field2, ElementsKind kind) { | 1491 HValue* instance_type, HValue* bit_field2, ElementsKind kind) { |
| 1492 ASSERT(IsExternalArrayElementsKind(kind)); | 1492 DCHECK(IsExternalArrayElementsKind(kind)); |
| 1493 | 1493 |
| 1494 BuildElementsKindLimitCheck(if_builder, bit_field2, kind); | 1494 BuildElementsKindLimitCheck(if_builder, bit_field2, kind); |
| 1495 | 1495 |
| 1496 Push(BuildUncheckedMonomorphicElementAccess(receiver, key, NULL, | 1496 Push(BuildUncheckedMonomorphicElementAccess(receiver, key, NULL, |
| 1497 false, kind, | 1497 false, kind, |
| 1498 LOAD, NEVER_RETURN_HOLE, | 1498 LOAD, NEVER_RETURN_HOLE, |
| 1499 STANDARD_STORE)); | 1499 STANDARD_STORE)); |
| 1500 } | 1500 } |
| 1501 | 1501 |
| 1502 | 1502 |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1717 return Pop(); | 1717 return Pop(); |
| 1718 } | 1718 } |
| 1719 | 1719 |
| 1720 | 1720 |
| 1721 Handle<Code> KeyedLoadGenericStub::GenerateCode() { | 1721 Handle<Code> KeyedLoadGenericStub::GenerateCode() { |
| 1722 return DoGenerateCode(this); | 1722 return DoGenerateCode(this); |
| 1723 } | 1723 } |
| 1724 | 1724 |
| 1725 | 1725 |
| 1726 } } // namespace v8::internal | 1726 } } // namespace v8::internal |
| OLD | NEW |