OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 "hydrogen.h" | 5 #include "hydrogen.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "v8.h" | 9 #include "v8.h" |
10 #include "allocation-site-scopes.h" | 10 #include "allocation-site-scopes.h" |
(...skipping 1219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1230 return Add<HCheckHeapObject>(obj); | 1230 return Add<HCheckHeapObject>(obj); |
1231 } | 1231 } |
1232 | 1232 |
1233 | 1233 |
1234 void HGraphBuilder::FinishExitWithHardDeoptimization(const char* reason) { | 1234 void HGraphBuilder::FinishExitWithHardDeoptimization(const char* reason) { |
1235 Add<HDeoptimize>(reason, Deoptimizer::EAGER); | 1235 Add<HDeoptimize>(reason, Deoptimizer::EAGER); |
1236 FinishExitCurrentBlock(New<HAbnormalExit>()); | 1236 FinishExitCurrentBlock(New<HAbnormalExit>()); |
1237 } | 1237 } |
1238 | 1238 |
1239 | 1239 |
1240 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, Handle<Map> map) { | |
1241 return Add<HCheckMaps>(obj, map, top_info()); | |
1242 } | |
1243 | |
1244 | |
1245 HValue* HGraphBuilder::BuildCheckString(HValue* string) { | 1240 HValue* HGraphBuilder::BuildCheckString(HValue* string) { |
1246 if (!string->type().IsString()) { | 1241 if (!string->type().IsString()) { |
1247 ASSERT(!string->IsConstant() || | 1242 ASSERT(!string->IsConstant() || |
1248 !HConstant::cast(string)->HasStringValue()); | 1243 !HConstant::cast(string)->HasStringValue()); |
1249 BuildCheckHeapObject(string); | 1244 BuildCheckHeapObject(string); |
1250 return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING); | 1245 return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING); |
1251 } | 1246 } |
1252 return string; | 1247 return string; |
1253 } | 1248 } |
1254 | 1249 |
(...skipping 880 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2135 (elements_kind == FAST_ELEMENTS && access_type == STORE)) { | 2130 (elements_kind == FAST_ELEMENTS && access_type == STORE)) { |
2136 checked_object->ClearDependsOnFlag(kElementsKind); | 2131 checked_object->ClearDependsOnFlag(kElementsKind); |
2137 } | 2132 } |
2138 | 2133 |
2139 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); | 2134 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); |
2140 bool fast_elements = IsFastObjectElementsKind(elements_kind); | 2135 bool fast_elements = IsFastObjectElementsKind(elements_kind); |
2141 HValue* elements = AddLoadElements(checked_object); | 2136 HValue* elements = AddLoadElements(checked_object); |
2142 if (access_type == STORE && (fast_elements || fast_smi_only_elements) && | 2137 if (access_type == STORE && (fast_elements || fast_smi_only_elements) && |
2143 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { | 2138 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { |
2144 HCheckMaps* check_cow_map = Add<HCheckMaps>( | 2139 HCheckMaps* check_cow_map = Add<HCheckMaps>( |
2145 elements, isolate()->factory()->fixed_array_map(), top_info()); | 2140 elements, isolate()->factory()->fixed_array_map()); |
2146 check_cow_map->ClearDependsOnFlag(kElementsKind); | 2141 check_cow_map->ClearDependsOnFlag(kElementsKind); |
2147 } | 2142 } |
2148 HInstruction* length = NULL; | 2143 HInstruction* length = NULL; |
2149 if (is_js_array) { | 2144 if (is_js_array) { |
2150 length = Add<HLoadNamedField>( | 2145 length = Add<HLoadNamedField>( |
2151 checked_object, static_cast<HValue*>(NULL), | 2146 checked_object, static_cast<HValue*>(NULL), |
2152 HObjectAccess::ForArrayLength(elements_kind)); | 2147 HObjectAccess::ForArrayLength(elements_kind)); |
2153 } else { | 2148 } else { |
2154 length = AddLoadFixedArrayLength(elements); | 2149 length = AddLoadFixedArrayLength(elements); |
2155 } | 2150 } |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2209 } else { | 2204 } else { |
2210 checked_key = Add<HBoundsCheck>(key, length); | 2205 checked_key = Add<HBoundsCheck>(key, length); |
2211 | 2206 |
2212 if (access_type == STORE && (fast_elements || fast_smi_only_elements)) { | 2207 if (access_type == STORE && (fast_elements || fast_smi_only_elements)) { |
2213 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { | 2208 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { |
2214 NoObservableSideEffectsScope no_effects(this); | 2209 NoObservableSideEffectsScope no_effects(this); |
2215 elements = BuildCopyElementsOnWrite(checked_object, elements, | 2210 elements = BuildCopyElementsOnWrite(checked_object, elements, |
2216 elements_kind, length); | 2211 elements_kind, length); |
2217 } else { | 2212 } else { |
2218 HCheckMaps* check_cow_map = Add<HCheckMaps>( | 2213 HCheckMaps* check_cow_map = Add<HCheckMaps>( |
2219 elements, isolate()->factory()->fixed_array_map(), top_info()); | 2214 elements, isolate()->factory()->fixed_array_map()); |
2220 check_cow_map->ClearDependsOnFlag(kElementsKind); | 2215 check_cow_map->ClearDependsOnFlag(kElementsKind); |
2221 } | 2216 } |
2222 } | 2217 } |
2223 } | 2218 } |
2224 return AddElementAccess(elements, checked_key, val, checked_object, | 2219 return AddElementAccess(elements, checked_key, val, checked_object, |
2225 elements_kind, access_type, load_mode); | 2220 elements_kind, access_type, load_mode); |
2226 } | 2221 } |
2227 | 2222 |
2228 | 2223 |
2229 | 2224 |
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2677 | 2672 |
2678 if (some_case_missing) { | 2673 if (some_case_missing) { |
2679 if_nil.Then(); | 2674 if_nil.Then(); |
2680 if_nil.Else(); | 2675 if_nil.Else(); |
2681 if (type->NumClasses() == 1) { | 2676 if (type->NumClasses() == 1) { |
2682 BuildCheckHeapObject(value); | 2677 BuildCheckHeapObject(value); |
2683 // For ICs, the map checked below is a sentinel map that gets replaced by | 2678 // For ICs, the map checked below is a sentinel map that gets replaced by |
2684 // the monomorphic map when the code is used as a template to generate a | 2679 // the monomorphic map when the code is used as a template to generate a |
2685 // new IC. For optimized functions, there is no sentinel map, the map | 2680 // new IC. For optimized functions, there is no sentinel map, the map |
2686 // emitted below is the actual monomorphic map. | 2681 // emitted below is the actual monomorphic map. |
2687 BuildCheckMap(value, type->Classes().Current()); | 2682 Add<HCheckMaps>(value, type->Classes().Current()); |
2688 } else { | 2683 } else { |
2689 if_nil.Deopt("Too many undetectable types"); | 2684 if_nil.Deopt("Too many undetectable types"); |
2690 } | 2685 } |
2691 } | 2686 } |
2692 | 2687 |
2693 if_nil.CaptureContinuation(continuation); | 2688 if_nil.CaptureContinuation(continuation); |
2694 } | 2689 } |
2695 | 2690 |
2696 | 2691 |
2697 void HGraphBuilder::BuildCreateAllocationMemento( | 2692 void HGraphBuilder::BuildCreateAllocationMemento( |
(...skipping 2431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5129 Handle<Map> map = property->GetReceiverType(); | 5124 Handle<Map> map = property->GetReceiverType(); |
5130 Handle<String> name = property->key()->AsPropertyName(); | 5125 Handle<String> name = property->key()->AsPropertyName(); |
5131 HInstruction* store; | 5126 HInstruction* store; |
5132 if (map.is_null()) { | 5127 if (map.is_null()) { |
5133 // If we don't know the monomorphic type, do a generic store. | 5128 // If we don't know the monomorphic type, do a generic store. |
5134 CHECK_ALIVE(store = BuildNamedGeneric( | 5129 CHECK_ALIVE(store = BuildNamedGeneric( |
5135 STORE, literal, name, value)); | 5130 STORE, literal, name, value)); |
5136 } else { | 5131 } else { |
5137 PropertyAccessInfo info(this, STORE, ToType(map), name); | 5132 PropertyAccessInfo info(this, STORE, ToType(map), name); |
5138 if (info.CanAccessMonomorphic()) { | 5133 if (info.CanAccessMonomorphic()) { |
5139 HValue* checked_literal = BuildCheckMap(literal, map); | 5134 HValue* checked_literal = Add<HCheckMaps>(literal, map); |
5140 ASSERT(!info.lookup()->IsPropertyCallbacks()); | 5135 ASSERT(!info.lookup()->IsPropertyCallbacks()); |
5141 store = BuildMonomorphicAccess( | 5136 store = BuildMonomorphicAccess( |
5142 &info, literal, checked_literal, value, | 5137 &info, literal, checked_literal, value, |
5143 BailoutId::None(), BailoutId::None()); | 5138 BailoutId::None(), BailoutId::None()); |
5144 } else { | 5139 } else { |
5145 CHECK_ALIVE(store = BuildNamedGeneric( | 5140 CHECK_ALIVE(store = BuildNamedGeneric( |
5146 STORE, literal, name, value)); | 5141 STORE, literal, name, value)); |
5147 } | 5142 } |
5148 } | 5143 } |
5149 AddInstruction(store); | 5144 AddInstruction(store); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5256 // TODO(mvstanton): Consider a flag to turn off creation of any | 5251 // TODO(mvstanton): Consider a flag to turn off creation of any |
5257 // AllocationMementos for this call: we are in crankshaft and should have | 5252 // AllocationMementos for this call: we are in crankshaft and should have |
5258 // learned enough about transition behavior to stop emitting mementos. | 5253 // learned enough about transition behavior to stop emitting mementos. |
5259 Runtime::FunctionId function_id = Runtime::kHiddenCreateArrayLiteral; | 5254 Runtime::FunctionId function_id = Runtime::kHiddenCreateArrayLiteral; |
5260 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), | 5255 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), |
5261 Runtime::FunctionForId(function_id), | 5256 Runtime::FunctionForId(function_id), |
5262 4); | 5257 4); |
5263 | 5258 |
5264 // De-opt if elements kind changed from boilerplate_elements_kind. | 5259 // De-opt if elements kind changed from boilerplate_elements_kind. |
5265 Handle<Map> map = Handle<Map>(boilerplate_object->map(), isolate()); | 5260 Handle<Map> map = Handle<Map>(boilerplate_object->map(), isolate()); |
5266 literal = Add<HCheckMaps>(literal, map, top_info()); | 5261 literal = Add<HCheckMaps>(literal, map); |
5267 } | 5262 } |
5268 | 5263 |
5269 // The array is expected in the bailout environment during computation | 5264 // The array is expected in the bailout environment during computation |
5270 // of the property values and is the value of the entire expression. | 5265 // of the property values and is the value of the entire expression. |
5271 Push(literal); | 5266 Push(literal); |
5272 // The literal index is on the stack, too. | 5267 // The literal index is on the stack, too. |
5273 Push(Add<HConstant>(expr->literal_index())); | 5268 Push(Add<HConstant>(expr->literal_index())); |
5274 | 5269 |
5275 HInstruction* elements = NULL; | 5270 HInstruction* elements = NULL; |
5276 | 5271 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5309 } | 5304 } |
5310 | 5305 |
5311 Drop(1); // array literal index | 5306 Drop(1); // array literal index |
5312 return ast_context()->ReturnValue(Pop()); | 5307 return ast_context()->ReturnValue(Pop()); |
5313 } | 5308 } |
5314 | 5309 |
5315 | 5310 |
5316 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object, | 5311 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object, |
5317 Handle<Map> map) { | 5312 Handle<Map> map) { |
5318 BuildCheckHeapObject(object); | 5313 BuildCheckHeapObject(object); |
5319 return Add<HCheckMaps>(object, map, top_info()); | 5314 return Add<HCheckMaps>(object, map); |
5320 } | 5315 } |
5321 | 5316 |
5322 | 5317 |
5323 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedField( | 5318 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedField( |
5324 PropertyAccessInfo* info, | 5319 PropertyAccessInfo* info, |
5325 HValue* checked_object) { | 5320 HValue* checked_object) { |
5326 // See if this is a load for an immutable property | 5321 // See if this is a load for an immutable property |
5327 if (checked_object->ActualValue()->IsConstant() && | 5322 if (checked_object->ActualValue()->IsConstant() && |
5328 info->lookup()->IsCacheable() && | 5323 info->lookup()->IsCacheable() && |
5329 info->lookup()->IsReadOnly() && info->lookup()->IsDontDelete()) { | 5324 info->lookup()->IsReadOnly() && info->lookup()->IsDontDelete()) { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5392 checked_object, static_cast<HValue*>(NULL), heap_number_access); | 5387 checked_object, static_cast<HValue*>(NULL), heap_number_access); |
5393 heap_number->set_type(HType::HeapNumber()); | 5388 heap_number->set_type(HType::HeapNumber()); |
5394 instr = New<HStoreNamedField>(heap_number, | 5389 instr = New<HStoreNamedField>(heap_number, |
5395 HObjectAccess::ForHeapNumberValue(), | 5390 HObjectAccess::ForHeapNumberValue(), |
5396 value, STORE_TO_INITIALIZED_ENTRY); | 5391 value, STORE_TO_INITIALIZED_ENTRY); |
5397 } | 5392 } |
5398 } else { | 5393 } else { |
5399 if (!info->field_maps()->is_empty()) { | 5394 if (!info->field_maps()->is_empty()) { |
5400 ASSERT(field_access.representation().IsHeapObject()); | 5395 ASSERT(field_access.representation().IsHeapObject()); |
5401 BuildCheckHeapObject(value); | 5396 BuildCheckHeapObject(value); |
5402 if (info->field_maps()->length() == 1) { | 5397 value = Add<HCheckMaps>(value, info->field_maps()); |
5403 // TODO(bmeurer): Also apply stable maps optimization to the else case! | |
5404 value = BuildCheckMap(value, info->field_maps()->first()); | |
5405 } else { | |
5406 value = Add<HCheckMaps>(value, info->field_maps()); | |
5407 } | |
5408 | 5398 |
5409 // TODO(bmeurer): This is a dirty hack to avoid repeating the smi check | 5399 // TODO(bmeurer): This is a dirty hack to avoid repeating the smi check |
5410 // that was already performed by the HCheckHeapObject above in the | 5400 // that was already performed by the HCheckHeapObject above in the |
5411 // HStoreNamedField below. We should really do this right instead and | 5401 // HStoreNamedField below. We should really do this right instead and |
5412 // make Crankshaft aware of Representation::HeapObject(). | 5402 // make Crankshaft aware of Representation::HeapObject(). |
5413 field_access = field_access.WithRepresentation(Representation::Tagged()); | 5403 field_access = field_access.WithRepresentation(Representation::Tagged()); |
5414 } | 5404 } |
5415 | 5405 |
5416 // This is a normal store. | 5406 // This is a normal store. |
5417 instr = New<HStoreNamedField>( | 5407 instr = New<HStoreNamedField>( |
(...skipping 933 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6351 | 6341 |
6352 | 6342 |
6353 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( | 6343 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( |
6354 HValue* object, | 6344 HValue* object, |
6355 HValue* key, | 6345 HValue* key, |
6356 HValue* val, | 6346 HValue* val, |
6357 HValue* dependency, | 6347 HValue* dependency, |
6358 Handle<Map> map, | 6348 Handle<Map> map, |
6359 PropertyAccessType access_type, | 6349 PropertyAccessType access_type, |
6360 KeyedAccessStoreMode store_mode) { | 6350 KeyedAccessStoreMode store_mode) { |
6361 HCheckMaps* checked_object = Add<HCheckMaps>(object, map, top_info(), | 6351 HCheckMaps* checked_object = Add<HCheckMaps>(object, map, dependency); |
6362 dependency); | |
6363 if (dependency) { | 6352 if (dependency) { |
6364 checked_object->ClearDependsOnFlag(kElementsKind); | 6353 checked_object->ClearDependsOnFlag(kElementsKind); |
6365 } | 6354 } |
6366 | 6355 |
6367 if (access_type == STORE && map->prototype()->IsJSObject()) { | 6356 if (access_type == STORE && map->prototype()->IsJSObject()) { |
6368 // monomorphic stores need a prototype chain check because shape | 6357 // monomorphic stores need a prototype chain check because shape |
6369 // changes could allow callbacks on elements in the chain that | 6358 // changes could allow callbacks on elements in the chain that |
6370 // aren't compatible with monomorphic keyed stores. | 6359 // aren't compatible with monomorphic keyed stores. |
6371 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 6360 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
6372 Object* holder = map->prototype(); | 6361 Object* holder = map->prototype(); |
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6831 CHECK_ALIVE(VisitForValue(expr->obj())); | 6820 CHECK_ALIVE(VisitForValue(expr->obj())); |
6832 if ((!expr->IsFunctionPrototype() && !expr->key()->IsPropertyName()) || | 6821 if ((!expr->IsFunctionPrototype() && !expr->key()->IsPropertyName()) || |
6833 expr->IsStringAccess()) { | 6822 expr->IsStringAccess()) { |
6834 CHECK_ALIVE(VisitForValue(expr->key())); | 6823 CHECK_ALIVE(VisitForValue(expr->key())); |
6835 } | 6824 } |
6836 | 6825 |
6837 BuildLoad(expr, expr->id()); | 6826 BuildLoad(expr, expr->id()); |
6838 } | 6827 } |
6839 | 6828 |
6840 | 6829 |
6841 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant, | 6830 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant) { |
6842 CompilationInfo* info) { | 6831 HCheckMaps* check = Add<HCheckMaps>( |
6843 HConstant* constant_value = New<HConstant>(constant); | 6832 Add<HConstant>(constant), handle(constant->map())); |
6844 Handle<Map> map(constant->map(), info->isolate()); | |
6845 | |
6846 if (constant->map()->CanOmitMapChecks()) { | |
6847 Map::AddDependentCompilationInfo( | |
6848 map, DependentCode::kPrototypeCheckGroup, info); | |
6849 return constant_value; | |
6850 } | |
6851 | |
6852 AddInstruction(constant_value); | |
6853 HCheckMaps* check = Add<HCheckMaps>(constant_value, map, info); | |
6854 check->ClearDependsOnFlag(kElementsKind); | 6833 check->ClearDependsOnFlag(kElementsKind); |
6855 return check; | 6834 return check; |
6856 } | 6835 } |
6857 | 6836 |
6858 | 6837 |
6859 HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype, | 6838 HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype, |
6860 Handle<JSObject> holder) { | 6839 Handle<JSObject> holder) { |
6861 while (holder.is_null() || !prototype.is_identical_to(holder)) { | 6840 while (holder.is_null() || !prototype.is_identical_to(holder)) { |
6862 BuildConstantMapCheck(prototype, top_info()); | 6841 BuildConstantMapCheck(prototype); |
6863 Object* next_prototype = prototype->GetPrototype(); | 6842 Object* next_prototype = prototype->GetPrototype(); |
6864 if (next_prototype->IsNull()) return NULL; | 6843 if (next_prototype->IsNull()) return NULL; |
6865 CHECK(next_prototype->IsJSObject()); | 6844 CHECK(next_prototype->IsJSObject()); |
6866 prototype = handle(JSObject::cast(next_prototype)); | 6845 prototype = handle(JSObject::cast(next_prototype)); |
6867 } | 6846 } |
6868 | 6847 return BuildConstantMapCheck(prototype); |
6869 HInstruction* checked_object = BuildConstantMapCheck(prototype, top_info()); | |
6870 if (!checked_object->IsLinked()) AddInstruction(checked_object); | |
6871 return checked_object; | |
6872 } | 6848 } |
6873 | 6849 |
6874 | 6850 |
6875 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, | 6851 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, |
6876 Handle<Map> receiver_map) { | 6852 Handle<Map> receiver_map) { |
6877 if (!holder.is_null()) { | 6853 if (!holder.is_null()) { |
6878 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); | 6854 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); |
6879 BuildCheckPrototypeMaps(prototype, holder); | 6855 BuildCheckPrototypeMaps(prototype, holder); |
6880 } | 6856 } |
6881 } | 6857 } |
(...skipping 4785 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11667 if (ShouldProduceTraceOutput()) { | 11643 if (ShouldProduceTraceOutput()) { |
11668 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11644 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
11669 } | 11645 } |
11670 | 11646 |
11671 #ifdef DEBUG | 11647 #ifdef DEBUG |
11672 graph_->Verify(false); // No full verify. | 11648 graph_->Verify(false); // No full verify. |
11673 #endif | 11649 #endif |
11674 } | 11650 } |
11675 | 11651 |
11676 } } // namespace v8::internal | 11652 } } // namespace v8::internal |
OLD | NEW |