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 |