| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 1586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1597 if_objectiskey.Then(); | 1597 if_objectiskey.Then(); |
| 1598 { | 1598 { |
| 1599 // Make the key_index available. | 1599 // Make the key_index available. |
| 1600 Push(key_index); | 1600 Push(key_index); |
| 1601 } | 1601 } |
| 1602 if_objectiskey.JoinContinuation(&found); | 1602 if_objectiskey.JoinContinuation(&found); |
| 1603 } | 1603 } |
| 1604 if_objectissmi.Else(); | 1604 if_objectissmi.Else(); |
| 1605 { | 1605 { |
| 1606 if (type->Is(Type::Smi())) { | 1606 if (type->Is(Type::Smi())) { |
| 1607 if_objectissmi.Deopt("Excepted smi"); | 1607 if_objectissmi.Deopt("Expected smi"); |
| 1608 } else { | 1608 } else { |
| 1609 // Check if the object is a heap number. | 1609 // Check if the object is a heap number. |
| 1610 IfBuilder if_objectisnumber(this); | 1610 IfBuilder if_objectisnumber(this); |
| 1611 if_objectisnumber.If<HCompareMap>( | 1611 if_objectisnumber.If<HCompareMap>( |
| 1612 object, isolate()->factory()->heap_number_map()); | 1612 object, isolate()->factory()->heap_number_map()); |
| 1613 if_objectisnumber.Then(); | 1613 if_objectisnumber.Then(); |
| 1614 { | 1614 { |
| 1615 // Compute hash for heap number similar to double_get_hash(). | 1615 // Compute hash for heap number similar to double_get_hash(). |
| 1616 HValue* low = Add<HLoadNamedField>( | 1616 HValue* low = Add<HLoadNamedField>( |
| 1617 object, HObjectAccess::ForHeapNumberValueLowestBits()); | 1617 object, HObjectAccess::ForHeapNumberValueLowestBits()); |
| (...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2232 | 2232 |
| 2233 HConstant* empty_fixed_array = | 2233 HConstant* empty_fixed_array = |
| 2234 Add<HConstant>(isolate()->factory()->empty_fixed_array()); | 2234 Add<HConstant>(isolate()->factory()->empty_fixed_array()); |
| 2235 | 2235 |
| 2236 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); | 2236 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); |
| 2237 Add<HStoreNamedField>(array, access, empty_fixed_array); | 2237 Add<HStoreNamedField>(array, access, empty_fixed_array); |
| 2238 Add<HStoreNamedField>(array, HObjectAccess::ForArrayLength(elements_kind), | 2238 Add<HStoreNamedField>(array, HObjectAccess::ForArrayLength(elements_kind), |
| 2239 length_field); | 2239 length_field); |
| 2240 | 2240 |
| 2241 if (mode == TRACK_ALLOCATION_SITE) { | 2241 if (mode == TRACK_ALLOCATION_SITE) { |
| 2242 BuildCreateAllocationMemento(array, | 2242 BuildCreateAllocationMemento( |
| 2243 JSArray::kSize, | 2243 array, Add<HConstant>(JSArray::kSize), allocation_site_payload); |
| 2244 allocation_site_payload); | |
| 2245 if (FLAG_allocation_site_pretenuring) { | |
| 2246 // TODO(mvstanton): move this code into BuildCreateAllocationMemento when | |
| 2247 // constructed arrays also pay attention to pretenuring. | |
| 2248 HObjectAccess access = | |
| 2249 HObjectAccess::ForAllocationSiteOffset( | |
| 2250 AllocationSite::kMementoCreateCountOffset); | |
| 2251 HValue* create_info = Add<HLoadNamedField>(allocation_site_payload, | |
| 2252 access); | |
| 2253 HInstruction* new_create_info = | |
| 2254 AddUncasted<HAdd>(create_info, graph()->GetConstant1()); | |
| 2255 new_create_info->ClearFlag(HValue::kCanOverflow); | |
| 2256 HStoreNamedField* store = Add<HStoreNamedField>(allocation_site_payload, | |
| 2257 access, new_create_info); | |
| 2258 // No write barrier needed to store a smi. | |
| 2259 store->SkipWriteBarrier(); | |
| 2260 } | |
| 2261 } | 2244 } |
| 2262 | 2245 |
| 2263 int elements_location = JSArray::kSize; | 2246 int elements_location = JSArray::kSize; |
| 2264 if (mode == TRACK_ALLOCATION_SITE) { | 2247 if (mode == TRACK_ALLOCATION_SITE) { |
| 2265 elements_location += AllocationMemento::kSize; | 2248 elements_location += AllocationMemento::kSize; |
| 2266 } | 2249 } |
| 2267 | 2250 |
| 2268 HValue* elements = Add<HInnerAllocatedObject>(array, elements_location); | 2251 HInnerAllocatedObject* elements = Add<HInnerAllocatedObject>( |
| 2252 array, Add<HConstant>(elements_location)); |
| 2269 Add<HStoreNamedField>(array, HObjectAccess::ForElementsPointer(), elements); | 2253 Add<HStoreNamedField>(array, HObjectAccess::ForElementsPointer(), elements); |
| 2270 return static_cast<HInnerAllocatedObject*>(elements); | 2254 return elements; |
| 2271 } | 2255 } |
| 2272 | 2256 |
| 2273 | 2257 |
| 2274 HInstruction* HGraphBuilder::AddElementAccess( | 2258 HInstruction* HGraphBuilder::AddElementAccess( |
| 2275 HValue* elements, | 2259 HValue* elements, |
| 2276 HValue* checked_key, | 2260 HValue* checked_key, |
| 2277 HValue* val, | 2261 HValue* val, |
| 2278 HValue* dependency, | 2262 HValue* dependency, |
| 2279 ElementsKind elements_kind, | 2263 ElementsKind elements_kind, |
| 2280 bool is_store, | 2264 bool is_store, |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2490 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { | 2474 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { |
| 2491 if ((i != JSArray::kElementsOffset) || (length == 0)) { | 2475 if ((i != JSArray::kElementsOffset) || (length == 0)) { |
| 2492 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); | 2476 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); |
| 2493 Add<HStoreNamedField>(object, access, | 2477 Add<HStoreNamedField>(object, access, |
| 2494 Add<HLoadNamedField>(boilerplate, access)); | 2478 Add<HLoadNamedField>(boilerplate, access)); |
| 2495 } | 2479 } |
| 2496 } | 2480 } |
| 2497 | 2481 |
| 2498 // Create an allocation site info if requested. | 2482 // Create an allocation site info if requested. |
| 2499 if (mode == TRACK_ALLOCATION_SITE) { | 2483 if (mode == TRACK_ALLOCATION_SITE) { |
| 2500 BuildCreateAllocationMemento(object, JSArray::kSize, allocation_site); | 2484 BuildCreateAllocationMemento( |
| 2485 object, Add<HConstant>(JSArray::kSize), allocation_site); |
| 2501 } | 2486 } |
| 2502 | 2487 |
| 2503 if (length > 0) { | 2488 if (length > 0) { |
| 2504 HValue* boilerplate_elements = AddLoadElements(boilerplate); | 2489 HValue* boilerplate_elements = AddLoadElements(boilerplate); |
| 2505 HValue* object_elements; | 2490 HValue* object_elements; |
| 2506 if (IsFastDoubleElementsKind(kind)) { | 2491 if (IsFastDoubleElementsKind(kind)) { |
| 2507 HValue* elems_size = Add<HConstant>(FixedDoubleArray::SizeFor(length)); | 2492 HValue* elems_size = Add<HConstant>(FixedDoubleArray::SizeFor(length)); |
| 2508 object_elements = Add<HAllocate>(elems_size, HType::JSArray(), | 2493 object_elements = Add<HAllocate>(elems_size, HType::JSArray(), |
| 2509 NOT_TENURED, FIXED_DOUBLE_ARRAY_TYPE); | 2494 NOT_TENURED, FIXED_DOUBLE_ARRAY_TYPE); |
| 2510 } else { | 2495 } else { |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2583 BuildCheckMap(value, type->Classes().Current()); | 2568 BuildCheckMap(value, type->Classes().Current()); |
| 2584 } else { | 2569 } else { |
| 2585 if_nil.Deopt("Too many undetectable types"); | 2570 if_nil.Deopt("Too many undetectable types"); |
| 2586 } | 2571 } |
| 2587 } | 2572 } |
| 2588 | 2573 |
| 2589 if_nil.CaptureContinuation(continuation); | 2574 if_nil.CaptureContinuation(continuation); |
| 2590 } | 2575 } |
| 2591 | 2576 |
| 2592 | 2577 |
| 2593 HValue* HGraphBuilder::BuildCreateAllocationMemento(HValue* previous_object, | 2578 void HGraphBuilder::BuildCreateAllocationMemento( |
| 2594 int previous_object_size, | 2579 HValue* previous_object, |
| 2595 HValue* alloc_site) { | 2580 HValue* previous_object_size, |
| 2596 ASSERT(alloc_site != NULL); | 2581 HValue* allocation_site) { |
| 2597 HInnerAllocatedObject* alloc_memento = Add<HInnerAllocatedObject>( | 2582 ASSERT(allocation_site != NULL); |
| 2583 HInnerAllocatedObject* allocation_memento = Add<HInnerAllocatedObject>( |
| 2598 previous_object, previous_object_size); | 2584 previous_object, previous_object_size); |
| 2599 Handle<Map> alloc_memento_map = | 2585 AddStoreMapConstant( |
| 2600 isolate()->factory()->allocation_memento_map(); | 2586 allocation_memento, isolate()->factory()->allocation_memento_map()); |
| 2601 AddStoreMapConstant(alloc_memento, alloc_memento_map); | 2587 Add<HStoreNamedField>( |
| 2602 HObjectAccess access = HObjectAccess::ForAllocationMementoSite(); | 2588 allocation_memento, |
| 2603 Add<HStoreNamedField>(alloc_memento, access, alloc_site); | 2589 HObjectAccess::ForAllocationMementoSite(), |
| 2604 return alloc_memento; | 2590 allocation_site); |
| 2591 if (FLAG_allocation_site_pretenuring) { |
| 2592 HValue* memento_create_count = Add<HLoadNamedField>( |
| 2593 allocation_site, HObjectAccess::ForAllocationSiteOffset( |
| 2594 AllocationSite::kMementoCreateCountOffset)); |
| 2595 memento_create_count = AddUncasted<HAdd>( |
| 2596 memento_create_count, graph()->GetConstant1()); |
| 2597 // This smi value is reset to zero after every gc, overflow isn't a problem |
| 2598 // since the counter is bounded by the new space size. |
| 2599 memento_create_count->ClearFlag(HValue::kCanOverflow); |
| 2600 HStoreNamedField* store = Add<HStoreNamedField>( |
| 2601 allocation_site, HObjectAccess::ForAllocationSiteOffset( |
| 2602 AllocationSite::kMementoCreateCountOffset), memento_create_count); |
| 2603 // No write barrier needed to store a smi. |
| 2604 store->SkipWriteBarrier(); |
| 2605 } |
| 2605 } | 2606 } |
| 2606 | 2607 |
| 2607 | 2608 |
| 2608 HInstruction* HGraphBuilder::BuildGetNativeContext() { | 2609 HInstruction* HGraphBuilder::BuildGetNativeContext() { |
| 2609 // Get the global context, then the native context | 2610 // Get the global context, then the native context |
| 2610 HInstruction* global_object = Add<HGlobalObject>(); | 2611 HInstruction* global_object = Add<HGlobalObject>(); |
| 2611 HObjectAccess access = HObjectAccess::ForJSObjectOffset( | 2612 HObjectAccess access = HObjectAccess::ForJSObjectOffset( |
| 2612 GlobalObject::kNativeContextOffset); | 2613 GlobalObject::kNativeContextOffset); |
| 2613 return Add<HLoadNamedField>(global_object, access); | 2614 return Add<HLoadNamedField>(global_object, access); |
| 2614 } | 2615 } |
| (...skipping 950 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3565 | 3566 |
| 3566 void TestContext::BuildBranch(HValue* value) { | 3567 void TestContext::BuildBranch(HValue* value) { |
| 3567 // We expect the graph to be in edge-split form: there is no edge that | 3568 // We expect the graph to be in edge-split form: there is no edge that |
| 3568 // connects a branch node to a join node. We conservatively ensure that | 3569 // connects a branch node to a join node. We conservatively ensure that |
| 3569 // property by always adding an empty block on the outgoing edges of this | 3570 // property by always adding an empty block on the outgoing edges of this |
| 3570 // branch. | 3571 // branch. |
| 3571 HOptimizedGraphBuilder* builder = owner(); | 3572 HOptimizedGraphBuilder* builder = owner(); |
| 3572 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { | 3573 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { |
| 3573 builder->Bailout(kArgumentsObjectValueInATestContext); | 3574 builder->Bailout(kArgumentsObjectValueInATestContext); |
| 3574 } | 3575 } |
| 3575 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); | |
| 3576 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); | |
| 3577 ToBooleanStub::Types expected(condition()->to_boolean_types()); | 3576 ToBooleanStub::Types expected(condition()->to_boolean_types()); |
| 3578 builder->FinishCurrentBlock(builder->New<HBranch>( | 3577 ReturnControl(owner()->New<HBranch>(value, expected), BailoutId::None()); |
| 3579 value, expected, empty_true, empty_false)); | |
| 3580 | |
| 3581 owner()->Goto(empty_true, if_true(), builder->function_state()); | |
| 3582 owner()->Goto(empty_false , if_false(), builder->function_state()); | |
| 3583 builder->set_current_block(NULL); | |
| 3584 } | 3578 } |
| 3585 | 3579 |
| 3586 | 3580 |
| 3587 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts. | 3581 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts. |
| 3588 #define CHECK_BAILOUT(call) \ | 3582 #define CHECK_BAILOUT(call) \ |
| 3589 do { \ | 3583 do { \ |
| 3590 call; \ | 3584 call; \ |
| 3591 if (HasStackOverflow()) return; \ | 3585 if (HasStackOverflow()) return; \ |
| 3592 } while (false) | 3586 } while (false) |
| 3593 | 3587 |
| (...skipping 3978 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7572 if (args->length() != 2) return false; | 7566 if (args->length() != 2) return false; |
| 7573 | 7567 |
| 7574 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); | 7568 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); |
| 7575 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; | 7569 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; |
| 7576 HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); | 7570 HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); |
| 7577 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; | 7571 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; |
| 7578 | 7572 |
| 7579 // Found pattern f.apply(receiver, arguments). | 7573 // Found pattern f.apply(receiver, arguments). |
| 7580 CHECK_ALIVE_OR_RETURN(VisitForValue(prop->obj()), true); | 7574 CHECK_ALIVE_OR_RETURN(VisitForValue(prop->obj()), true); |
| 7581 HValue* function = Top(); | 7575 HValue* function = Top(); |
| 7582 // The function get here may be an undefined constant if lookup fails. | |
| 7583 if (function->IsConstant() && | |
| 7584 !HConstant::cast(function)->handle(isolate())->IsJSFunction()) { | |
| 7585 Drop(1); | |
| 7586 return false; | |
| 7587 } | |
| 7588 | 7576 |
| 7589 AddCheckConstantFunction(expr->holder(), function, function_map); | 7577 AddCheckConstantFunction(expr->holder(), function, function_map); |
| 7590 Drop(1); | 7578 Drop(1); |
| 7591 | 7579 |
| 7592 CHECK_ALIVE_OR_RETURN(VisitForValue(args->at(0)), true); | 7580 CHECK_ALIVE_OR_RETURN(VisitForValue(args->at(0)), true); |
| 7593 HValue* receiver = Pop(); | 7581 HValue* receiver = Pop(); |
| 7594 | 7582 |
| 7595 if (function_state()->outer() == NULL) { | 7583 if (function_state()->outer() == NULL) { |
| 7596 HInstruction* elements = Add<HArgumentsElements>(false); | 7584 HInstruction* elements = Add<HArgumentsElements>(false); |
| 7597 HInstruction* length = Add<HArgumentsLength>(elements); | 7585 HInstruction* length = Add<HArgumentsLength>(elements); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 7609 function_state()->entry()->arguments_object()->arguments_count()); | 7597 function_state()->entry()->arguments_object()->arguments_count()); |
| 7610 HArgumentsObject* args = function_state()->entry()->arguments_object(); | 7598 HArgumentsObject* args = function_state()->entry()->arguments_object(); |
| 7611 const ZoneList<HValue*>* arguments_values = args->arguments_values(); | 7599 const ZoneList<HValue*>* arguments_values = args->arguments_values(); |
| 7612 int arguments_count = arguments_values->length(); | 7600 int arguments_count = arguments_values->length(); |
| 7613 Push(BuildWrapReceiver(receiver, function)); | 7601 Push(BuildWrapReceiver(receiver, function)); |
| 7614 for (int i = 1; i < arguments_count; i++) { | 7602 for (int i = 1; i < arguments_count; i++) { |
| 7615 Push(arguments_values->at(i)); | 7603 Push(arguments_values->at(i)); |
| 7616 } | 7604 } |
| 7617 | 7605 |
| 7618 Handle<JSFunction> known_function; | 7606 Handle<JSFunction> known_function; |
| 7619 if (function->IsConstant()) { | 7607 if (function->IsConstant() && |
| 7620 HConstant* constant_function = HConstant::cast(function); | 7608 HConstant::cast(function)->handle(isolate())->IsJSFunction()) { |
| 7621 known_function = Handle<JSFunction>::cast( | 7609 known_function = Handle<JSFunction>::cast( |
| 7622 constant_function->handle(isolate())); | 7610 HConstant::cast(function)->handle(isolate())); |
| 7623 int args_count = arguments_count - 1; // Excluding receiver. | 7611 int args_count = arguments_count - 1; // Excluding receiver. |
| 7624 if (TryInlineApply(known_function, expr, args_count)) return true; | 7612 if (TryInlineApply(known_function, expr, args_count)) return true; |
| 7625 } | 7613 } |
| 7626 | 7614 |
| 7627 Drop(arguments_count - 1); | 7615 Drop(arguments_count - 1); |
| 7628 Push(Add<HPushArgument>(Pop())); | 7616 Push(Add<HPushArgument>(Pop())); |
| 7629 for (int i = 1; i < arguments_count; i++) { | 7617 for (int i = 1; i < arguments_count; i++) { |
| 7630 Push(Add<HPushArgument>(arguments_values->at(i))); | 7618 Push(Add<HPushArgument>(arguments_values->at(i))); |
| 7631 } | 7619 } |
| 7632 | 7620 |
| (...skipping 1252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8885 break; | 8873 break; |
| 8886 case Token::SUB: | 8874 case Token::SUB: |
| 8887 instr = AddUncasted<HSub>(left, right); | 8875 instr = AddUncasted<HSub>(left, right); |
| 8888 break; | 8876 break; |
| 8889 case Token::MUL: | 8877 case Token::MUL: |
| 8890 instr = AddUncasted<HMul>(left, right); | 8878 instr = AddUncasted<HMul>(left, right); |
| 8891 break; | 8879 break; |
| 8892 case Token::MOD: { | 8880 case Token::MOD: { |
| 8893 if (fixed_right_arg.has_value) { | 8881 if (fixed_right_arg.has_value) { |
| 8894 if (right->IsConstant()) { | 8882 if (right->IsConstant()) { |
| 8895 ASSERT_EQ(fixed_right_arg.value, | 8883 HConstant* c_right = HConstant::cast(right); |
| 8896 HConstant::cast(right)->Integer32Value()); | 8884 if (c_right->HasInteger32Value()) { |
| 8885 ASSERT_EQ(fixed_right_arg.value, c_right->Integer32Value()); |
| 8886 } |
| 8897 } else { | 8887 } else { |
| 8898 HConstant* fixed_right = Add<HConstant>( | 8888 HConstant* fixed_right = Add<HConstant>( |
| 8899 static_cast<int>(fixed_right_arg.value)); | 8889 static_cast<int>(fixed_right_arg.value)); |
| 8900 IfBuilder if_same(this); | 8890 IfBuilder if_same(this); |
| 8901 if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ); | 8891 if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ); |
| 8902 if_same.Then(); | 8892 if_same.Then(); |
| 8903 if_same.ElseDeopt("Unexpected RHS of binary operation"); | 8893 if_same.ElseDeopt("Unexpected RHS of binary operation"); |
| 8904 right = fixed_right; | 8894 right = fixed_right; |
| 8905 } | 8895 } |
| 8906 } | 8896 } |
| (...skipping 1933 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10840 if (ShouldProduceTraceOutput()) { | 10830 if (ShouldProduceTraceOutput()) { |
| 10841 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 10831 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 10842 } | 10832 } |
| 10843 | 10833 |
| 10844 #ifdef DEBUG | 10834 #ifdef DEBUG |
| 10845 graph_->Verify(false); // No full verify. | 10835 graph_->Verify(false); // No full verify. |
| 10846 #endif | 10836 #endif |
| 10847 } | 10837 } |
| 10848 | 10838 |
| 10849 } } // namespace v8::internal | 10839 } } // namespace v8::internal |
| OLD | NEW |