| 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 2626 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2637 previous_object, previous_object_size); | 2637 previous_object, previous_object_size); |
| 2638 AddStoreMapConstant( | 2638 AddStoreMapConstant( |
| 2639 allocation_memento, isolate()->factory()->allocation_memento_map()); | 2639 allocation_memento, isolate()->factory()->allocation_memento_map()); |
| 2640 Add<HStoreNamedField>( | 2640 Add<HStoreNamedField>( |
| 2641 allocation_memento, | 2641 allocation_memento, |
| 2642 HObjectAccess::ForAllocationMementoSite(), | 2642 HObjectAccess::ForAllocationMementoSite(), |
| 2643 allocation_site); | 2643 allocation_site); |
| 2644 if (FLAG_allocation_site_pretenuring) { | 2644 if (FLAG_allocation_site_pretenuring) { |
| 2645 HValue* memento_create_count = Add<HLoadNamedField>( | 2645 HValue* memento_create_count = Add<HLoadNamedField>( |
| 2646 allocation_site, HObjectAccess::ForAllocationSiteOffset( | 2646 allocation_site, HObjectAccess::ForAllocationSiteOffset( |
| 2647 AllocationSite::kMementoCreateCountOffset)); | 2647 AllocationSite::kPretenureCreateCountOffset)); |
| 2648 memento_create_count = AddUncasted<HAdd>( | 2648 memento_create_count = AddUncasted<HAdd>( |
| 2649 memento_create_count, graph()->GetConstant1()); | 2649 memento_create_count, graph()->GetConstant1()); |
| 2650 // This smi value is reset to zero after every gc, overflow isn't a problem | 2650 // This smi value is reset to zero after every gc, overflow isn't a problem |
| 2651 // since the counter is bounded by the new space size. | 2651 // since the counter is bounded by the new space size. |
| 2652 memento_create_count->ClearFlag(HValue::kCanOverflow); | 2652 memento_create_count->ClearFlag(HValue::kCanOverflow); |
| 2653 HStoreNamedField* store = Add<HStoreNamedField>( | 2653 HStoreNamedField* store = Add<HStoreNamedField>( |
| 2654 allocation_site, HObjectAccess::ForAllocationSiteOffset( | 2654 allocation_site, HObjectAccess::ForAllocationSiteOffset( |
| 2655 AllocationSite::kMementoCreateCountOffset), memento_create_count); | 2655 AllocationSite::kPretenureCreateCountOffset), memento_create_count); |
| 2656 // No write barrier needed to store a smi. | 2656 // No write barrier needed to store a smi. |
| 2657 store->SkipWriteBarrier(); | 2657 store->SkipWriteBarrier(); |
| 2658 } | 2658 } |
| 2659 } | 2659 } |
| 2660 | 2660 |
| 2661 | 2661 |
| 2662 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* closure) { |
| 2663 // Get the global context, then the native context |
| 2664 HInstruction* context = |
| 2665 Add<HLoadNamedField>(closure, HObjectAccess::ForFunctionContextPointer()); |
| 2666 HInstruction* global_object = Add<HLoadNamedField>(context, |
| 2667 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); |
| 2668 HObjectAccess access = HObjectAccess::ForJSObjectOffset( |
| 2669 GlobalObject::kNativeContextOffset); |
| 2670 return Add<HLoadNamedField>(global_object, access); |
| 2671 } |
| 2672 |
| 2673 |
| 2662 HInstruction* HGraphBuilder::BuildGetNativeContext() { | 2674 HInstruction* HGraphBuilder::BuildGetNativeContext() { |
| 2663 // Get the global context, then the native context | 2675 // Get the global context, then the native context |
| 2664 HInstruction* global_object = Add<HGlobalObject>(); | 2676 HInstruction* global_object = Add<HGlobalObject>(); |
| 2665 HObjectAccess access = HObjectAccess::ForJSObjectOffset( | 2677 HObjectAccess access = HObjectAccess::ForJSObjectOffset( |
| 2666 GlobalObject::kNativeContextOffset); | 2678 GlobalObject::kNativeContextOffset); |
| 2667 return Add<HLoadNamedField>(global_object, access); | 2679 return Add<HLoadNamedField>(global_object, access); |
| 2668 } | 2680 } |
| 2669 | 2681 |
| 2670 | 2682 |
| 2671 HInstruction* HGraphBuilder::BuildGetArrayFunction() { | 2683 HInstruction* HGraphBuilder::BuildGetArrayFunction() { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2711 return builder()->Add<HConstant>(map); | 2723 return builder()->Add<HConstant>(map); |
| 2712 } | 2724 } |
| 2713 | 2725 |
| 2714 if (constructor_function_ != NULL && kind_ == GetInitialFastElementsKind()) { | 2726 if (constructor_function_ != NULL && kind_ == GetInitialFastElementsKind()) { |
| 2715 // No need for a context lookup if the kind_ matches the initial | 2727 // No need for a context lookup if the kind_ matches the initial |
| 2716 // map, because we can just load the map in that case. | 2728 // map, because we can just load the map in that case. |
| 2717 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); | 2729 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); |
| 2718 return builder()->AddLoadNamedField(constructor_function_, access); | 2730 return builder()->AddLoadNamedField(constructor_function_, access); |
| 2719 } | 2731 } |
| 2720 | 2732 |
| 2721 HInstruction* native_context = builder()->BuildGetNativeContext(); | 2733 // TODO(mvstanton): we should always have a constructor function if we |
| 2734 // are creating a stub. |
| 2735 HInstruction* native_context = constructor_function_ != NULL |
| 2736 ? builder()->BuildGetNativeContext(constructor_function_) |
| 2737 : builder()->BuildGetNativeContext(); |
| 2738 |
| 2722 HInstruction* index = builder()->Add<HConstant>( | 2739 HInstruction* index = builder()->Add<HConstant>( |
| 2723 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); | 2740 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); |
| 2724 | 2741 |
| 2725 HInstruction* map_array = builder()->Add<HLoadKeyed>( | 2742 HInstruction* map_array = builder()->Add<HLoadKeyed>( |
| 2726 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | 2743 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
| 2727 | 2744 |
| 2728 HInstruction* kind_index = builder()->Add<HConstant>(kind_); | 2745 HInstruction* kind_index = builder()->Add<HConstant>(kind_); |
| 2729 | 2746 |
| 2730 return builder()->Add<HLoadKeyed>( | 2747 return builder()->Add<HLoadKeyed>( |
| 2731 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | 2748 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); |
| (...skipping 1582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4314 ASSERT(current_block() != NULL); | 4331 ASSERT(current_block() != NULL); |
| 4315 HBasicBlock* loop_entry = BuildLoopEntry(stmt); | 4332 HBasicBlock* loop_entry = BuildLoopEntry(stmt); |
| 4316 | 4333 |
| 4317 BreakAndContinueInfo break_info(stmt); | 4334 BreakAndContinueInfo break_info(stmt); |
| 4318 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); | 4335 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); |
| 4319 HBasicBlock* body_exit = | 4336 HBasicBlock* body_exit = |
| 4320 JoinContinue(stmt, current_block(), break_info.continue_block()); | 4337 JoinContinue(stmt, current_block(), break_info.continue_block()); |
| 4321 HBasicBlock* loop_successor = NULL; | 4338 HBasicBlock* loop_successor = NULL; |
| 4322 if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) { | 4339 if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) { |
| 4323 set_current_block(body_exit); | 4340 set_current_block(body_exit); |
| 4324 // The block for a true condition, the actual predecessor block of the | |
| 4325 // back edge. | |
| 4326 body_exit = graph()->CreateBasicBlock(); | |
| 4327 loop_successor = graph()->CreateBasicBlock(); | 4341 loop_successor = graph()->CreateBasicBlock(); |
| 4328 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor)); | 4342 if (stmt->cond()->ToBooleanIsFalse()) { |
| 4329 if (body_exit->HasPredecessor()) { | 4343 Goto(loop_successor); |
| 4344 body_exit = NULL; |
| 4345 } else { |
| 4346 // The block for a true condition, the actual predecessor block of the |
| 4347 // back edge. |
| 4348 body_exit = graph()->CreateBasicBlock(); |
| 4349 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor)); |
| 4350 } |
| 4351 if (body_exit != NULL && body_exit->HasPredecessor()) { |
| 4330 body_exit->SetJoinId(stmt->BackEdgeId()); | 4352 body_exit->SetJoinId(stmt->BackEdgeId()); |
| 4331 } else { | 4353 } else { |
| 4332 body_exit = NULL; | 4354 body_exit = NULL; |
| 4333 } | 4355 } |
| 4334 if (loop_successor->HasPredecessor()) { | 4356 if (loop_successor->HasPredecessor()) { |
| 4335 loop_successor->SetJoinId(stmt->ExitId()); | 4357 loop_successor->SetJoinId(stmt->ExitId()); |
| 4336 } else { | 4358 } else { |
| 4337 loop_successor = NULL; | 4359 loop_successor = NULL; |
| 4338 } | 4360 } |
| 4339 } | 4361 } |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4567 ASSERT(current_block()->HasPredecessor()); | 4589 ASSERT(current_block()->HasPredecessor()); |
| 4568 return Bailout(kDebuggerStatement); | 4590 return Bailout(kDebuggerStatement); |
| 4569 } | 4591 } |
| 4570 | 4592 |
| 4571 | 4593 |
| 4572 void HOptimizedGraphBuilder::VisitCaseClause(CaseClause* clause) { | 4594 void HOptimizedGraphBuilder::VisitCaseClause(CaseClause* clause) { |
| 4573 UNREACHABLE(); | 4595 UNREACHABLE(); |
| 4574 } | 4596 } |
| 4575 | 4597 |
| 4576 | 4598 |
| 4577 static Handle<SharedFunctionInfo> SearchSharedFunctionInfo( | |
| 4578 Code* unoptimized_code, FunctionLiteral* expr) { | |
| 4579 int start_position = expr->start_position(); | |
| 4580 for (RelocIterator it(unoptimized_code); !it.done(); it.next()) { | |
| 4581 RelocInfo* rinfo = it.rinfo(); | |
| 4582 if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; | |
| 4583 Object* obj = rinfo->target_object(); | |
| 4584 if (obj->IsSharedFunctionInfo()) { | |
| 4585 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); | |
| 4586 if (shared->start_position() == start_position) { | |
| 4587 return Handle<SharedFunctionInfo>(shared); | |
| 4588 } | |
| 4589 } | |
| 4590 } | |
| 4591 | |
| 4592 return Handle<SharedFunctionInfo>(); | |
| 4593 } | |
| 4594 | |
| 4595 | |
| 4596 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { | 4599 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 4597 ASSERT(!HasStackOverflow()); | 4600 ASSERT(!HasStackOverflow()); |
| 4598 ASSERT(current_block() != NULL); | 4601 ASSERT(current_block() != NULL); |
| 4599 ASSERT(current_block()->HasPredecessor()); | 4602 ASSERT(current_block()->HasPredecessor()); |
| 4600 Handle<SharedFunctionInfo> shared_info = | 4603 Handle<SharedFunctionInfo> shared_info = expr->shared_info(); |
| 4601 SearchSharedFunctionInfo(current_info()->shared_info()->code(), expr); | |
| 4602 if (shared_info.is_null()) { | 4604 if (shared_info.is_null()) { |
| 4603 shared_info = Compiler::BuildFunctionInfo(expr, current_info()->script()); | 4605 shared_info = Compiler::BuildFunctionInfo(expr, current_info()->script()); |
| 4604 } | 4606 } |
| 4605 // We also have a stack overflow if the recursive compilation did. | 4607 // We also have a stack overflow if the recursive compilation did. |
| 4606 if (HasStackOverflow()) return; | 4608 if (HasStackOverflow()) return; |
| 4607 HFunctionLiteral* instr = | 4609 HFunctionLiteral* instr = |
| 4608 New<HFunctionLiteral>(shared_info, expr->pretenure()); | 4610 New<HFunctionLiteral>(shared_info, expr->pretenure()); |
| 4609 return ast_context()->ReturnInstruction(instr, expr->id()); | 4611 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 4610 } | 4612 } |
| 4611 | 4613 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4680 HValue* context = environment()->context(); | 4682 HValue* context = environment()->context(); |
| 4681 int length = current_info()->scope()->ContextChainLength(var->scope()); | 4683 int length = current_info()->scope()->ContextChainLength(var->scope()); |
| 4682 while (length-- > 0) { | 4684 while (length-- > 0) { |
| 4683 context = Add<HOuterContext>(context); | 4685 context = Add<HOuterContext>(context); |
| 4684 } | 4686 } |
| 4685 return context; | 4687 return context; |
| 4686 } | 4688 } |
| 4687 | 4689 |
| 4688 | 4690 |
| 4689 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 4691 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
| 4692 if (expr->is_this()) { |
| 4693 current_info()->set_this_has_uses(true); |
| 4694 } |
| 4695 |
| 4690 ASSERT(!HasStackOverflow()); | 4696 ASSERT(!HasStackOverflow()); |
| 4691 ASSERT(current_block() != NULL); | 4697 ASSERT(current_block() != NULL); |
| 4692 ASSERT(current_block()->HasPredecessor()); | 4698 ASSERT(current_block()->HasPredecessor()); |
| 4693 Variable* variable = expr->var(); | 4699 Variable* variable = expr->var(); |
| 4694 switch (variable->location()) { | 4700 switch (variable->location()) { |
| 4695 case Variable::UNALLOCATED: { | 4701 case Variable::UNALLOCATED: { |
| 4696 if (IsLexicalVariableMode(variable->mode())) { | 4702 if (IsLexicalVariableMode(variable->mode())) { |
| 4697 // TODO(rossberg): should this be an ASSERT? | 4703 // TODO(rossberg): should this be an ASSERT? |
| 4698 return Bailout(kReferenceToGlobalLexicalVariable); | 4704 return Bailout(kReferenceToGlobalLexicalVariable); |
| 4699 } | 4705 } |
| (...skipping 2111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6811 | 6817 |
| 6812 | 6818 |
| 6813 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( | 6819 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( |
| 6814 Call* expr, | 6820 Call* expr, |
| 6815 HValue* receiver, | 6821 HValue* receiver, |
| 6816 SmallMapList* types, | 6822 SmallMapList* types, |
| 6817 Handle<String> name) { | 6823 Handle<String> name) { |
| 6818 if (TryCallPolymorphicAsMonomorphic(expr, receiver, types, name)) return; | 6824 if (TryCallPolymorphicAsMonomorphic(expr, receiver, types, name)) return; |
| 6819 | 6825 |
| 6820 int argument_count = expr->arguments()->length() + 1; // Includes receiver. | 6826 int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
| 6821 HBasicBlock* join = NULL; | |
| 6822 FunctionSorter order[kMaxCallPolymorphism]; | |
| 6823 int ordered_functions = 0; | |
| 6824 | 6827 |
| 6825 Handle<Map> initial_string_map( | 6828 Handle<Map> initial_string_map( |
| 6826 isolate()->native_context()->string_function()->initial_map()); | 6829 isolate()->native_context()->string_function()->initial_map()); |
| 6827 Handle<Map> string_marker_map( | 6830 Handle<Map> string_marker_map( |
| 6828 JSObject::cast(initial_string_map->prototype())->map()); | 6831 JSObject::cast(initial_string_map->prototype())->map()); |
| 6829 Handle<Map> initial_number_map( | 6832 Handle<Map> initial_number_map( |
| 6830 isolate()->native_context()->number_function()->initial_map()); | 6833 isolate()->native_context()->number_function()->initial_map()); |
| 6831 Handle<Map> number_marker_map( | 6834 Handle<Map> number_marker_map( |
| 6832 JSObject::cast(initial_number_map->prototype())->map()); | 6835 JSObject::cast(initial_number_map->prototype())->map()); |
| 6833 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map(); | 6836 Handle<Map> heap_number_map = isolate()->factory()->heap_number_map(); |
| 6834 | 6837 |
| 6835 bool handle_smi = false; | 6838 bool handle_smi = false; |
| 6836 | 6839 |
| 6840 // A map from functions to a set of receivers' maps. |
| 6841 struct FuncMapEntry { |
| 6842 Handle<JSFunction> func; |
| 6843 SmallMapList maps; |
| 6844 }; |
| 6845 FuncMapEntry func_map[kMaxCallPolymorphism]; |
| 6846 FunctionSorter order[kMaxCallPolymorphism]; |
| 6847 int func_count = 0; |
| 6848 int maps_count = 0; |
| 6849 |
| 6837 for (int i = 0; | 6850 for (int i = 0; |
| 6838 i < types->length() && ordered_functions < kMaxCallPolymorphism; | 6851 i < types->length() && func_count < kMaxCallPolymorphism; |
| 6839 ++i) { | 6852 ++i) { |
| 6840 Handle<Map> map = types->at(i); | 6853 Handle<Map> map = types->at(i); |
| 6841 if (expr->ComputeTarget(map, name)) { | 6854 if (expr->ComputeTarget(map, name)) { |
| 6842 if (map.is_identical_to(number_marker_map)) handle_smi = true; | 6855 if (map.is_identical_to(number_marker_map)) handle_smi = true; |
| 6843 order[ordered_functions++] = | 6856 |
| 6844 FunctionSorter(i, | 6857 // Try to find the target function among known targets. |
| 6845 expr->target()->shared()->profiler_ticks(), | 6858 int func_index = 0; |
| 6846 InliningAstSize(expr->target()), | 6859 for (; func_index < func_count; ++func_index) { |
| 6847 expr->target()->shared()->SourceSize()); | 6860 if (*func_map[func_index].func == *expr->target()) { |
| 6861 break; |
| 6862 } |
| 6863 } |
| 6864 FuncMapEntry* entry = &func_map[func_index]; |
| 6865 if (func_index == func_count) { |
| 6866 // Entry not found, "allocate" it. |
| 6867 entry->func = expr->target(); |
| 6868 entry->maps.Reserve(types->length() - maps_count, zone()); |
| 6869 order[func_index] = |
| 6870 FunctionSorter(func_index, |
| 6871 entry->func->shared()->profiler_ticks(), |
| 6872 InliningAstSize(entry->func), |
| 6873 entry->func->shared()->SourceSize()); |
| 6874 ++func_count; |
| 6875 } |
| 6876 entry->maps.Add(map, zone()); |
| 6877 ++maps_count; |
| 6848 } | 6878 } |
| 6849 } | 6879 } |
| 6850 | 6880 |
| 6851 std::sort(order, order + ordered_functions); | 6881 std::sort(order, order + func_count); |
| 6852 | 6882 |
| 6853 HBasicBlock* number_block = NULL; | 6883 HBasicBlock* number_block = NULL; |
| 6884 HBasicBlock* join = NULL; |
| 6854 | 6885 |
| 6855 for (int fn = 0; fn < ordered_functions; ++fn) { | 6886 if (func_count > 0) { |
| 6887 // Only needed once. |
| 6888 join = graph()->CreateBasicBlock(); |
| 6889 if (handle_smi) { |
| 6890 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); |
| 6891 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); |
| 6892 number_block = graph()->CreateBasicBlock(); |
| 6893 FinishCurrentBlock( |
| 6894 New<HIsSmiAndBranch>(receiver, empty_smi_block, not_smi_block)); |
| 6895 Goto(empty_smi_block, number_block); |
| 6896 set_current_block(not_smi_block); |
| 6897 } else { |
| 6898 BuildCheckHeapObject(receiver); |
| 6899 } |
| 6900 } |
| 6901 |
| 6902 for (int fn = 0; fn < func_count; ++fn) { |
| 6856 int i = order[fn].index(); | 6903 int i = order[fn].index(); |
| 6857 Handle<Map> map = types->at(i); | 6904 FuncMapEntry* func_map_entry = &func_map[i]; |
| 6858 if (fn == 0) { | 6905 |
| 6859 // Only needed once. | 6906 HBasicBlock* call_block = graph()->CreateBasicBlock(); |
| 6860 join = graph()->CreateBasicBlock(); | 6907 HBasicBlock* if_false = NULL; |
| 6861 if (handle_smi) { | 6908 |
| 6862 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); | 6909 int maps_count = func_map_entry->maps.length(); |
| 6863 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); | 6910 for (int m = 0; m < maps_count; ++m) { |
| 6864 number_block = graph()->CreateBasicBlock(); | 6911 Handle<Map> map = func_map_entry->maps.at(m); |
| 6865 FinishCurrentBlock(New<HIsSmiAndBranch>( | 6912 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
| 6866 receiver, empty_smi_block, not_smi_block)); | 6913 if_false = graph()->CreateBasicBlock(); |
| 6867 Goto(empty_smi_block, number_block); | 6914 HUnaryControlInstruction* compare; |
| 6868 set_current_block(not_smi_block); | 6915 |
| 6916 if (handle_smi && map.is_identical_to(number_marker_map)) { |
| 6917 compare = |
| 6918 New<HCompareMap>(receiver, heap_number_map, if_true, if_false); |
| 6919 map = initial_number_map; |
| 6920 expr->set_number_check( |
| 6921 Handle<JSObject>(JSObject::cast(map->prototype()))); |
| 6922 } else if (map.is_identical_to(string_marker_map)) { |
| 6923 compare = New<HIsStringAndBranch>(receiver, if_true, if_false); |
| 6924 map = initial_string_map; |
| 6925 expr->set_string_check( |
| 6926 Handle<JSObject>(JSObject::cast(map->prototype()))); |
| 6869 } else { | 6927 } else { |
| 6870 BuildCheckHeapObject(receiver); | 6928 compare = New<HCompareMap>(receiver, map, if_true, if_false); |
| 6929 expr->set_map_check(); |
| 6871 } | 6930 } |
| 6872 } | |
| 6873 HBasicBlock* if_true = graph()->CreateBasicBlock(); | |
| 6874 HBasicBlock* if_false = graph()->CreateBasicBlock(); | |
| 6875 HUnaryControlInstruction* compare; | |
| 6876 | 6931 |
| 6877 if (handle_smi && map.is_identical_to(number_marker_map)) { | 6932 FinishCurrentBlock(compare); |
| 6878 compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false); | 6933 |
| 6879 map = initial_number_map; | 6934 if (expr->check_type() == NUMBER_CHECK) { |
| 6880 expr->set_number_check( | 6935 Goto(if_true, number_block); |
| 6881 Handle<JSObject>(JSObject::cast(map->prototype()))); | 6936 if_true = number_block; |
| 6882 } else if (map.is_identical_to(string_marker_map)) { | 6937 number_block->SetJoinId(expr->id()); |
| 6883 compare = New<HIsStringAndBranch>(receiver, if_true, if_false); | 6938 } |
| 6884 map = initial_string_map; | 6939 set_current_block(if_true); |
| 6885 expr->set_string_check( | 6940 |
| 6886 Handle<JSObject>(JSObject::cast(map->prototype()))); | 6941 expr->ComputeTarget(map, name); |
| 6887 } else { | 6942 ASSERT(*expr->target() == *func_map_entry->func); |
| 6888 compare = New<HCompareMap>(receiver, map, if_true, if_false); | 6943 |
| 6889 expr->set_map_check(); | 6944 AddCheckPrototypeMaps(expr->holder(), map); |
| 6945 |
| 6946 Goto(if_true, call_block); |
| 6947 |
| 6948 set_current_block(if_false); |
| 6890 } | 6949 } |
| 6891 | 6950 |
| 6892 FinishCurrentBlock(compare); | 6951 // Generate call once for all corresponding maps. |
| 6952 call_block->SetJoinId(expr->id()); |
| 6953 set_current_block(call_block); |
| 6893 | 6954 |
| 6894 if (expr->check_type() == NUMBER_CHECK) { | |
| 6895 Goto(if_true, number_block); | |
| 6896 if_true = number_block; | |
| 6897 number_block->SetJoinId(expr->id()); | |
| 6898 } | |
| 6899 set_current_block(if_true); | |
| 6900 | |
| 6901 expr->ComputeTarget(map, name); | |
| 6902 AddCheckPrototypeMaps(expr->holder(), map); | |
| 6903 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { | 6955 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { |
| 6904 Handle<JSFunction> caller = current_info()->closure(); | 6956 Handle<JSFunction> caller = current_info()->closure(); |
| 6905 SmartArrayPointer<char> caller_name = | 6957 SmartArrayPointer<char> caller_name = |
| 6906 caller->shared()->DebugName()->ToCString(); | 6958 caller->shared()->DebugName()->ToCString(); |
| 6907 PrintF("Trying to inline the polymorphic call to %s from %s\n", | 6959 PrintF("Trying to inline the polymorphic call to %s from %s\n", |
| 6908 name->ToCString().get(), | 6960 name->ToCString().get(), |
| 6909 caller_name.get()); | 6961 caller_name.get()); |
| 6910 } | 6962 } |
| 6911 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { | 6963 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { |
| 6912 // Trying to inline will signal that we should bailout from the | 6964 // Trying to inline will signal that we should bailout from the |
| 6913 // entire compilation by setting stack overflow on the visitor. | 6965 // entire compilation by setting stack overflow on the visitor. |
| 6914 if (HasStackOverflow()) return; | 6966 if (HasStackOverflow()) return; |
| 6915 } else { | 6967 } else { |
| 6916 HCallConstantFunction* call = | 6968 HCallConstantFunction* call = |
| 6917 New<HCallConstantFunction>(expr->target(), argument_count); | 6969 New<HCallConstantFunction>(expr->target(), argument_count); |
| 6918 PreProcessCall(call); | 6970 PreProcessCall(call); |
| 6919 AddInstruction(call); | 6971 AddInstruction(call); |
| 6920 if (!ast_context()->IsEffect()) Push(call); | 6972 if (!ast_context()->IsEffect()) Push(call); |
| 6921 } | 6973 } |
| 6974 if (current_block() != NULL) Goto(join); |
| 6922 | 6975 |
| 6923 if (current_block() != NULL) Goto(join); | |
| 6924 set_current_block(if_false); | 6976 set_current_block(if_false); |
| 6925 } | 6977 } |
| 6926 | 6978 |
| 6927 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 6979 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
| 6928 // know about and do not want to handle ones we've never seen. Otherwise | 6980 // know about and do not want to handle ones we've never seen. Otherwise |
| 6929 // use a generic IC. | 6981 // use a generic IC. |
| 6930 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { | 6982 if (maps_count == types->length() && FLAG_deoptimize_uncommon_cases) { |
| 6931 // Because the deopt may be the only path in the polymorphic call, make sure | 6983 // Because the deopt may be the only path in the polymorphic call, make sure |
| 6932 // that the environment stack matches the depth on deopt that it otherwise | 6984 // that the environment stack matches the depth on deopt that it otherwise |
| 6933 // would have had after a successful call. | 6985 // would have had after a successful call. |
| 6934 Drop(argument_count); | 6986 Drop(argument_count); |
| 6935 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); | 6987 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); |
| 6936 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); | 6988 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); |
| 6937 } else { | 6989 } else { |
| 6938 HCallNamed* call = New<HCallNamed>(name, argument_count); | 6990 HCallNamed* call = New<HCallNamed>(name, argument_count); |
| 6939 PreProcessCall(call); | 6991 PreProcessCall(call); |
| 6940 | 6992 |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7170 ASSERT(target_shared->has_deoptimization_support()); | 7222 ASSERT(target_shared->has_deoptimization_support()); |
| 7171 AstTyper::Run(&target_info); | 7223 AstTyper::Run(&target_info); |
| 7172 | 7224 |
| 7173 // Save the pending call context. Set up new one for the inlined function. | 7225 // Save the pending call context. Set up new one for the inlined function. |
| 7174 // The function state is new-allocated because we need to delete it | 7226 // The function state is new-allocated because we need to delete it |
| 7175 // in two different places. | 7227 // in two different places. |
| 7176 FunctionState* target_state = new FunctionState( | 7228 FunctionState* target_state = new FunctionState( |
| 7177 this, &target_info, inlining_kind); | 7229 this, &target_info, inlining_kind); |
| 7178 | 7230 |
| 7179 HConstant* undefined = graph()->GetConstantUndefined(); | 7231 HConstant* undefined = graph()->GetConstantUndefined(); |
| 7180 bool undefined_receiver = HEnvironment::UseUndefinedReceiver( | 7232 |
| 7181 target, function, call_kind, inlining_kind); | |
| 7182 HEnvironment* inner_env = | 7233 HEnvironment* inner_env = |
| 7183 environment()->CopyForInlining(target, | 7234 environment()->CopyForInlining(target, |
| 7184 arguments_count, | 7235 arguments_count, |
| 7185 function, | 7236 function, |
| 7186 undefined, | 7237 undefined, |
| 7187 function_state()->inlining_kind(), | 7238 function_state()->inlining_kind()); |
| 7188 undefined_receiver); | |
| 7189 | 7239 |
| 7190 // TODO(jochen): Remove this #ifdef once A64's register allocator can allocate | 7240 // TODO(jochen): Remove this #ifdef once A64's register allocator can allocate |
| 7191 // cp. | 7241 // cp. |
| 7192 #if !V8_TARGET_ARCH_A64 | 7242 #if !V8_TARGET_ARCH_A64 |
| 7193 HConstant* context = Add<HConstant>(Handle<Context>(target->context())); | 7243 HConstant* context = Add<HConstant>(Handle<Context>(target->context())); |
| 7194 inner_env->BindContext(context); | 7244 inner_env->BindContext(context); |
| 7195 #endif | 7245 #endif |
| 7196 | 7246 |
| 7197 Add<HSimulate>(return_id); | 7247 Add<HSimulate>(return_id); |
| 7198 current_block()->UpdateEnvironment(inner_env); | 7248 current_block()->UpdateEnvironment(inner_env); |
| 7199 HArgumentsObject* arguments_object = NULL; | 7249 HArgumentsObject* arguments_object = NULL; |
| 7200 | 7250 |
| 7201 // If the function uses arguments object create and bind one, also copy | 7251 // If the function uses arguments object create and bind one, also copy |
| 7202 // current arguments values to use them for materialization. | 7252 // current arguments values to use them for materialization. |
| 7203 if (function->scope()->arguments() != NULL) { | 7253 if (function->scope()->arguments() != NULL) { |
| 7204 ASSERT(function->scope()->arguments()->IsStackAllocated()); | 7254 ASSERT(function->scope()->arguments()->IsStackAllocated()); |
| 7205 HEnvironment* arguments_env = inner_env->arguments_environment(); | 7255 HEnvironment* arguments_env = inner_env->arguments_environment(); |
| 7206 int arguments_count = arguments_env->parameter_count(); | 7256 int arguments_count = arguments_env->parameter_count(); |
| 7207 arguments_object = Add<HArgumentsObject>(arguments_count); | 7257 arguments_object = Add<HArgumentsObject>(arguments_count); |
| 7208 inner_env->Bind(function->scope()->arguments(), arguments_object); | 7258 inner_env->Bind(function->scope()->arguments(), arguments_object); |
| 7209 for (int i = 0; i < arguments_count; i++) { | 7259 for (int i = 0; i < arguments_count; i++) { |
| 7210 arguments_object->AddArgument(arguments_env->Lookup(i), zone()); | 7260 arguments_object->AddArgument(arguments_env->Lookup(i), zone()); |
| 7211 } | 7261 } |
| 7212 } | 7262 } |
| 7213 | 7263 |
| 7214 HEnterInlined* enter_inlined = | 7264 HEnterInlined* enter_inlined = |
| 7215 Add<HEnterInlined>(target, arguments_count, function, | 7265 Add<HEnterInlined>(target, arguments_count, function, |
| 7216 function_state()->inlining_kind(), | 7266 function_state()->inlining_kind(), |
| 7217 function->scope()->arguments(), | 7267 function->scope()->arguments(), |
| 7218 arguments_object, undefined_receiver); | 7268 arguments_object); |
| 7219 function_state()->set_entry(enter_inlined); | 7269 function_state()->set_entry(enter_inlined); |
| 7220 | 7270 |
| 7221 VisitDeclarations(target_info.scope()->declarations()); | 7271 VisitDeclarations(target_info.scope()->declarations()); |
| 7222 VisitStatements(function->body()); | 7272 VisitStatements(function->body()); |
| 7223 if (HasStackOverflow()) { | 7273 if (HasStackOverflow()) { |
| 7224 // Bail out if the inline function did, as we cannot residualize a call | 7274 // Bail out if the inline function did, as we cannot residualize a call |
| 7225 // instead. | 7275 // instead. |
| 7226 TraceInline(target, caller, "inline graph construction failed"); | 7276 TraceInline(target, caller, "inline graph construction failed"); |
| 7227 target_shared->DisableOptimization(kInliningBailedOut); | 7277 target_shared->DisableOptimization(kInliningBailedOut); |
| 7228 inline_bailout_ = true; | 7278 inline_bailout_ = true; |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7577 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); | 7627 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); |
| 7578 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; | 7628 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; |
| 7579 HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); | 7629 HValue* arg_two_value = LookupAndMakeLive(arg_two->var()); |
| 7580 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; | 7630 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; |
| 7581 | 7631 |
| 7582 // Found pattern f.apply(receiver, arguments). | 7632 // Found pattern f.apply(receiver, arguments). |
| 7583 CHECK_ALIVE_OR_RETURN(VisitForValue(prop->obj()), true); | 7633 CHECK_ALIVE_OR_RETURN(VisitForValue(prop->obj()), true); |
| 7584 HValue* function = Top(); | 7634 HValue* function = Top(); |
| 7585 | 7635 |
| 7586 AddCheckConstantFunction(expr->holder(), function, function_map); | 7636 AddCheckConstantFunction(expr->holder(), function, function_map); |
| 7587 Drop(1); | |
| 7588 | 7637 |
| 7589 CHECK_ALIVE_OR_RETURN(VisitForValue(args->at(0)), true); | 7638 CHECK_ALIVE_OR_RETURN(VisitForValue(args->at(0)), true); |
| 7590 HValue* receiver = Pop(); | 7639 HValue* receiver = Pop(); |
| 7591 | 7640 |
| 7641 Drop(1); // Pop the function. |
| 7642 |
| 7592 if (function_state()->outer() == NULL) { | 7643 if (function_state()->outer() == NULL) { |
| 7593 HInstruction* elements = Add<HArgumentsElements>(false); | 7644 HInstruction* elements = Add<HArgumentsElements>(false); |
| 7594 HInstruction* length = Add<HArgumentsLength>(elements); | 7645 HInstruction* length = Add<HArgumentsLength>(elements); |
| 7595 HValue* wrapped_receiver = BuildWrapReceiver(receiver, function); | 7646 HValue* wrapped_receiver = BuildWrapReceiver(receiver, function); |
| 7596 HInstruction* result = New<HApplyArguments>(function, | 7647 HInstruction* result = New<HApplyArguments>(function, |
| 7597 wrapped_receiver, | 7648 wrapped_receiver, |
| 7598 length, | 7649 length, |
| 7599 elements); | 7650 elements); |
| 7600 ast_context()->ReturnInstruction(result, expr->id()); | 7651 ast_context()->ReturnInstruction(result, expr->id()); |
| 7601 return true; | 7652 return true; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 7630 HInvokeFunction* call = New<HInvokeFunction>(function, | 7681 HInvokeFunction* call = New<HInvokeFunction>(function, |
| 7631 known_function, | 7682 known_function, |
| 7632 arguments_count); | 7683 arguments_count); |
| 7633 Drop(arguments_count); | 7684 Drop(arguments_count); |
| 7634 ast_context()->ReturnInstruction(call, expr->id()); | 7685 ast_context()->ReturnInstruction(call, expr->id()); |
| 7635 return true; | 7686 return true; |
| 7636 } | 7687 } |
| 7637 } | 7688 } |
| 7638 | 7689 |
| 7639 | 7690 |
| 7691 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function, |
| 7692 Handle<JSFunction> target) { |
| 7693 SharedFunctionInfo* shared = target->shared(); |
| 7694 if (shared->is_classic_mode() && !shared->native()) { |
| 7695 HValue* context = Add<HLoadNamedField>( |
| 7696 function, |
| 7697 HObjectAccess::ForJSObjectOffset(JSFunction::kContextOffset)); |
| 7698 HValue* global_object = Add<HLoadNamedField>( |
| 7699 context, |
| 7700 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); |
| 7701 return Add<HLoadNamedField>( |
| 7702 global_object, |
| 7703 HObjectAccess::ForJSObjectOffset( |
| 7704 GlobalObject::kGlobalReceiverOffset)); |
| 7705 } |
| 7706 return graph()->GetConstantUndefined(); |
| 7707 } |
| 7708 |
| 7709 |
| 7640 void HOptimizedGraphBuilder::VisitCall(Call* expr) { | 7710 void HOptimizedGraphBuilder::VisitCall(Call* expr) { |
| 7641 ASSERT(!HasStackOverflow()); | 7711 ASSERT(!HasStackOverflow()); |
| 7642 ASSERT(current_block() != NULL); | 7712 ASSERT(current_block() != NULL); |
| 7643 ASSERT(current_block()->HasPredecessor()); | 7713 ASSERT(current_block()->HasPredecessor()); |
| 7644 Expression* callee = expr->expression(); | 7714 Expression* callee = expr->expression(); |
| 7645 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 7715 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
| 7646 HInstruction* call = NULL; | 7716 HInstruction* call = NULL; |
| 7647 | 7717 |
| 7648 Property* prop = callee->AsProperty(); | 7718 Property* prop = callee->AsProperty(); |
| 7649 if (prop != NULL) { | 7719 if (prop != NULL) { |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7744 if (type == kUseCell && | 7814 if (type == kUseCell && |
| 7745 !current_info()->global_object()->IsAccessCheckNeeded()) { | 7815 !current_info()->global_object()->IsAccessCheckNeeded()) { |
| 7746 Handle<GlobalObject> global(current_info()->global_object()); | 7816 Handle<GlobalObject> global(current_info()->global_object()); |
| 7747 known_global_function = expr->ComputeGlobalTarget(global, &lookup); | 7817 known_global_function = expr->ComputeGlobalTarget(global, &lookup); |
| 7748 } | 7818 } |
| 7749 if (known_global_function) { | 7819 if (known_global_function) { |
| 7750 // Push the global object instead of the global receiver because | 7820 // Push the global object instead of the global receiver because |
| 7751 // code generated by the full code generator expects it. | 7821 // code generated by the full code generator expects it. |
| 7752 HGlobalObject* global_object = Add<HGlobalObject>(); | 7822 HGlobalObject* global_object = Add<HGlobalObject>(); |
| 7753 Push(global_object); | 7823 Push(global_object); |
| 7824 |
| 7754 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 7825 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 7755 | 7826 |
| 7756 CHECK_ALIVE(VisitForValue(expr->expression())); | 7827 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 7757 HValue* function = Pop(); | 7828 HValue* function = Pop(); |
| 7758 Add<HCheckValue>(function, expr->target()); | 7829 Add<HCheckValue>(function, expr->target()); |
| 7759 | 7830 |
| 7760 // Replace the global object with the global receiver. | 7831 // Patch the global object on the stack by the expected receiver. |
| 7761 HGlobalReceiver* global_receiver = Add<HGlobalReceiver>(global_object); | 7832 HValue* receiver = ImplicitReceiverFor(function, expr->target()); |
| 7762 // Index of the receiver from the top of the expression stack. | |
| 7763 const int receiver_index = argument_count - 1; | 7833 const int receiver_index = argument_count - 1; |
| 7764 ASSERT(environment()->ExpressionStackAt(receiver_index)-> | 7834 environment()->SetExpressionStackAt(receiver_index, receiver); |
| 7765 IsGlobalObject()); | |
| 7766 environment()->SetExpressionStackAt(receiver_index, global_receiver); | |
| 7767 | 7835 |
| 7768 if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop. | 7836 if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop. |
| 7769 if (FLAG_trace_inlining) { | 7837 if (FLAG_trace_inlining) { |
| 7770 PrintF("Inlining builtin "); | 7838 PrintF("Inlining builtin "); |
| 7771 expr->target()->ShortPrint(); | 7839 expr->target()->ShortPrint(); |
| 7772 PrintF("\n"); | 7840 PrintF("\n"); |
| 7773 } | 7841 } |
| 7774 return; | 7842 return; |
| 7775 } | 7843 } |
| 7776 if (TryInlineCall(expr)) return; | 7844 if (TryInlineCall(expr)) return; |
| 7777 | 7845 |
| 7778 if (expr->target().is_identical_to(current_info()->closure())) { | 7846 if (expr->target().is_identical_to(current_info()->closure())) { |
| 7779 graph()->MarkRecursive(); | 7847 graph()->MarkRecursive(); |
| 7780 } | 7848 } |
| 7781 | 7849 |
| 7782 if (CallStubCompiler::HasCustomCallGenerator(expr->target())) { | 7850 if (CallStubCompiler::HasCustomCallGenerator(expr->target())) { |
| 7851 // We're about to install a contextual IC, which expects the global |
| 7852 // object as receiver rather than the global proxy. |
| 7853 HGlobalObject* global_object = Add<HGlobalObject>(); |
| 7854 const int receiver_index = argument_count - 1; |
| 7855 environment()->SetExpressionStackAt(receiver_index, global_object); |
| 7783 // When the target has a custom call IC generator, use the IC, | 7856 // When the target has a custom call IC generator, use the IC, |
| 7784 // because it is likely to generate better code. | 7857 // because it is likely to generate better code. |
| 7785 call = PreProcessCall(New<HCallNamed>(var->name(), argument_count)); | 7858 call = PreProcessCall(New<HCallGlobal>(var->name(), argument_count)); |
| 7786 } else { | 7859 } else { |
| 7787 call = PreProcessCall(New<HCallKnownGlobal>( | 7860 call = PreProcessCall(New<HCallKnownGlobal>( |
| 7788 expr->target(), argument_count)); | 7861 expr->target(), argument_count)); |
| 7789 } | 7862 } |
| 7790 } else { | 7863 } else { |
| 7791 HGlobalObject* receiver = Add<HGlobalObject>(); | 7864 HGlobalObject* receiver = Add<HGlobalObject>(); |
| 7792 Push(Add<HPushArgument>(receiver)); | 7865 Push(Add<HPushArgument>(receiver)); |
| 7793 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 7866 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
| 7794 | 7867 |
| 7795 call = New<HCallGlobal>(var->name(), argument_count); | 7868 call = New<HCallGlobal>(var->name(), argument_count); |
| 7796 Drop(argument_count); | 7869 Drop(argument_count); |
| 7797 } | 7870 } |
| 7798 | 7871 |
| 7799 } else if (expr->IsMonomorphic()) { | 7872 } else if (expr->IsMonomorphic()) { |
| 7800 // The function is on the stack in the unoptimized code during | 7873 // The function is on the stack in the unoptimized code during |
| 7801 // evaluation of the arguments. | 7874 // evaluation of the arguments. |
| 7802 CHECK_ALIVE(VisitForValue(expr->expression())); | 7875 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 7803 HValue* function = Top(); | 7876 HValue* function = Top(); |
| 7804 HGlobalObject* global = Add<HGlobalObject>(); | 7877 |
| 7805 HGlobalReceiver* receiver = Add<HGlobalReceiver>(global); | 7878 Add<HCheckValue>(function, expr->target()); |
| 7879 |
| 7880 HValue* receiver = ImplicitReceiverFor(function, expr->target()); |
| 7806 Push(receiver); | 7881 Push(receiver); |
| 7882 |
| 7807 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 7883 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 7808 Add<HCheckValue>(function, expr->target()); | |
| 7809 | 7884 |
| 7810 if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function. | 7885 if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function. |
| 7811 if (FLAG_trace_inlining) { | 7886 if (FLAG_trace_inlining) { |
| 7812 PrintF("Inlining builtin "); | 7887 PrintF("Inlining builtin "); |
| 7813 expr->target()->ShortPrint(); | 7888 expr->target()->ShortPrint(); |
| 7814 PrintF("\n"); | 7889 PrintF("\n"); |
| 7815 } | 7890 } |
| 7816 return; | 7891 return; |
| 7817 } | 7892 } |
| 7818 | 7893 |
| 7819 if (TryInlineCall(expr, true)) { // Drop function from environment. | 7894 if (TryInlineCall(expr, true)) { // Drop function from environment. |
| 7820 return; | 7895 return; |
| 7821 } else { | 7896 } else { |
| 7822 call = PreProcessCall(New<HInvokeFunction>(function, expr->target(), | 7897 call = PreProcessCall(New<HInvokeFunction>(function, expr->target(), |
| 7823 argument_count)); | 7898 argument_count)); |
| 7824 Drop(1); // The function. | 7899 Drop(1); // The function. |
| 7825 } | 7900 } |
| 7826 | 7901 |
| 7827 } else { | 7902 } else { |
| 7828 CHECK_ALIVE(VisitForValue(expr->expression())); | 7903 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 7829 HValue* function = Top(); | 7904 HValue* function = Top(); |
| 7830 HGlobalObject* global_object = Add<HGlobalObject>(); | 7905 HValue* receiver = graph()->GetConstantUndefined(); |
| 7831 HGlobalReceiver* receiver = Add<HGlobalReceiver>(global_object); | |
| 7832 Push(Add<HPushArgument>(receiver)); | 7906 Push(Add<HPushArgument>(receiver)); |
| 7833 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 7907 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
| 7834 | 7908 call = New<HCallFunction>( |
| 7835 call = New<HCallFunction>(function, argument_count); | 7909 function, argument_count, NORMAL_CONTEXTUAL_CALL); |
| 7836 Drop(argument_count + 1); | 7910 Drop(argument_count + 1); |
| 7837 } | 7911 } |
| 7838 } | 7912 } |
| 7839 | 7913 |
| 7840 return ast_context()->ReturnInstruction(call, expr->id()); | 7914 return ast_context()->ReturnInstruction(call, expr->id()); |
| 7841 } | 7915 } |
| 7842 | 7916 |
| 7843 | 7917 |
| 7844 void HOptimizedGraphBuilder::BuildInlinedCallNewArray(CallNew* expr) { | 7918 void HOptimizedGraphBuilder::BuildInlinedCallNewArray(CallNew* expr) { |
| 7845 NoObservableSideEffectsScope no_effects(this); | 7919 NoObservableSideEffectsScope no_effects(this); |
| 7846 | 7920 |
| 7847 int argument_count = expr->arguments()->length(); | 7921 int argument_count = expr->arguments()->length(); |
| 7848 // We should at least have the constructor on the expression stack. | 7922 // We should at least have the constructor on the expression stack. |
| 7849 HValue* constructor = environment()->ExpressionStackAt(argument_count); | 7923 HValue* constructor = environment()->ExpressionStackAt(argument_count); |
| 7850 | 7924 |
| 7851 ElementsKind kind = expr->elements_kind(); | 7925 ElementsKind kind = expr->elements_kind(); |
| 7852 Handle<Cell> cell = expr->allocation_info_cell(); | 7926 Handle<Cell> cell = expr->allocation_info_cell(); |
| 7853 AllocationSite* site = AllocationSite::cast(cell->value()); | 7927 Handle<AllocationSite> site(AllocationSite::cast(cell->value())); |
| 7854 | 7928 |
| 7855 // Register on the site for deoptimization if the cell value changes. | 7929 // Register on the site for deoptimization if the cell value changes. |
| 7856 site->AddDependentCompilationInfo(AllocationSite::TRANSITIONS, top_info()); | 7930 AllocationSite::AddDependentCompilationInfo( |
| 7931 site, AllocationSite::TRANSITIONS, top_info()); |
| 7857 HInstruction* cell_instruction = Add<HConstant>(cell); | 7932 HInstruction* cell_instruction = Add<HConstant>(cell); |
| 7858 | 7933 |
| 7859 // In the single constant argument case, we may have to adjust elements kind | 7934 // In the single constant argument case, we may have to adjust elements kind |
| 7860 // to avoid creating a packed non-empty array. | 7935 // to avoid creating a packed non-empty array. |
| 7861 if (argument_count == 1 && !IsHoleyElementsKind(kind)) { | 7936 if (argument_count == 1 && !IsHoleyElementsKind(kind)) { |
| 7862 HValue* argument = environment()->Top(); | 7937 HValue* argument = environment()->Top(); |
| 7863 if (argument->IsConstant()) { | 7938 if (argument->IsConstant()) { |
| 7864 HConstant* constant_argument = HConstant::cast(argument); | 7939 HConstant* constant_argument = HConstant::cast(argument); |
| 7865 ASSERT(constant_argument->HasSmiValue()); | 7940 ASSERT(constant_argument->HasSmiValue()); |
| 7866 int constant_array_size = constant_argument->Integer32Value(); | 7941 int constant_array_size = constant_argument->Integer32Value(); |
| (...skipping 842 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8709 } | 8784 } |
| 8710 return number; | 8785 return number; |
| 8711 } | 8786 } |
| 8712 | 8787 |
| 8713 | 8788 |
| 8714 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) { | 8789 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) { |
| 8715 if (value->IsConstant()) { | 8790 if (value->IsConstant()) { |
| 8716 HConstant* constant = HConstant::cast(value); | 8791 HConstant* constant = HConstant::cast(value); |
| 8717 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone()); | 8792 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone()); |
| 8718 if (number.has_value) { | 8793 if (number.has_value) { |
| 8719 *expected = handle(Type::Number(), isolate()); | 8794 *expected = Type::Number(isolate()); |
| 8720 return AddInstruction(number.value); | 8795 return AddInstruction(number.value); |
| 8721 } | 8796 } |
| 8722 } | 8797 } |
| 8723 | 8798 |
| 8724 // We put temporary values on the stack, which don't correspond to anything | 8799 // We put temporary values on the stack, which don't correspond to anything |
| 8725 // in baseline code. Since nothing is observable we avoid recording those | 8800 // in baseline code. Since nothing is observable we avoid recording those |
| 8726 // pushes with a NoObservableSideEffectsScope. | 8801 // pushes with a NoObservableSideEffectsScope. |
| 8727 NoObservableSideEffectsScope no_effects(this); | 8802 NoObservableSideEffectsScope no_effects(this); |
| 8728 | 8803 |
| 8729 Handle<Type> expected_type = *expected; | 8804 Handle<Type> expected_type = *expected; |
| 8730 | 8805 |
| 8731 // Separate the number type from the rest. | 8806 // Separate the number type from the rest. |
| 8732 Handle<Type> expected_obj = handle(Type::Intersect( | 8807 Handle<Type> expected_obj = Type::Intersect( |
| 8733 expected_type, handle(Type::NonNumber(), isolate())), isolate()); | 8808 expected_type, Type::NonNumber(isolate()), isolate()); |
| 8734 Handle<Type> expected_number = handle(Type::Intersect( | 8809 Handle<Type> expected_number = Type::Intersect( |
| 8735 expected_type, handle(Type::Number(), isolate())), isolate()); | 8810 expected_type, Type::Number(isolate()), isolate()); |
| 8736 | 8811 |
| 8737 // We expect to get a number. | 8812 // We expect to get a number. |
| 8738 // (We need to check first, since Type::None->Is(Type::Any()) == true. | 8813 // (We need to check first, since Type::None->Is(Type::Any()) == true. |
| 8739 if (expected_obj->Is(Type::None())) { | 8814 if (expected_obj->Is(Type::None())) { |
| 8740 ASSERT(!expected_number->Is(Type::None())); | 8815 ASSERT(!expected_number->Is(Type::None())); |
| 8741 return value; | 8816 return value; |
| 8742 } | 8817 } |
| 8743 | 8818 |
| 8744 if (expected_obj->Is(Type::Undefined())) { | 8819 if (expected_obj->Is(Type::Undefined())) { |
| 8745 // This is already done by HChange. | 8820 // This is already done by HChange. |
| 8746 *expected = handle(Type::Union( | 8821 *expected = Type::Union( |
| 8747 expected_number, handle(Type::Double(), isolate())), isolate()); | 8822 expected_number, Type::Double(isolate()), isolate()); |
| 8748 return value; | 8823 return value; |
| 8749 } | 8824 } |
| 8750 | 8825 |
| 8751 return value; | 8826 return value; |
| 8752 } | 8827 } |
| 8753 | 8828 |
| 8754 | 8829 |
| 8755 HValue* HOptimizedGraphBuilder::BuildBinaryOperation( | 8830 HValue* HOptimizedGraphBuilder::BuildBinaryOperation( |
| 8756 BinaryOperation* expr, | 8831 BinaryOperation* expr, |
| 8757 HValue* left, | 8832 HValue* left, |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8799 | 8874 |
| 8800 bool maybe_string_add = op == Token::ADD && | 8875 bool maybe_string_add = op == Token::ADD && |
| 8801 (left_type->Maybe(Type::String()) || | 8876 (left_type->Maybe(Type::String()) || |
| 8802 right_type->Maybe(Type::String())); | 8877 right_type->Maybe(Type::String())); |
| 8803 | 8878 |
| 8804 if (left_type->Is(Type::None())) { | 8879 if (left_type->Is(Type::None())) { |
| 8805 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", | 8880 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", |
| 8806 Deoptimizer::SOFT); | 8881 Deoptimizer::SOFT); |
| 8807 // TODO(rossberg): we should be able to get rid of non-continuous | 8882 // TODO(rossberg): we should be able to get rid of non-continuous |
| 8808 // defaults. | 8883 // defaults. |
| 8809 left_type = handle(Type::Any(), isolate()); | 8884 left_type = Type::Any(isolate()); |
| 8810 } else { | 8885 } else { |
| 8811 if (!maybe_string_add) left = TruncateToNumber(left, &left_type); | 8886 if (!maybe_string_add) left = TruncateToNumber(left, &left_type); |
| 8812 left_rep = Representation::FromType(left_type); | 8887 left_rep = Representation::FromType(left_type); |
| 8813 } | 8888 } |
| 8814 | 8889 |
| 8815 if (right_type->Is(Type::None())) { | 8890 if (right_type->Is(Type::None())) { |
| 8816 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", | 8891 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", |
| 8817 Deoptimizer::SOFT); | 8892 Deoptimizer::SOFT); |
| 8818 right_type = handle(Type::Any(), isolate()); | 8893 right_type = Type::Any(isolate()); |
| 8819 } else { | 8894 } else { |
| 8820 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); | 8895 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); |
| 8821 right_rep = Representation::FromType(right_type); | 8896 right_rep = Representation::FromType(right_type); |
| 8822 } | 8897 } |
| 8823 | 8898 |
| 8824 // Special case for string addition here. | 8899 // Special case for string addition here. |
| 8825 if (op == Token::ADD && | 8900 if (op == Token::ADD && |
| 8826 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) { | 8901 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) { |
| 8827 // Validate type feedback for left argument. | 8902 // Validate type feedback for left argument. |
| 8828 if (left_type->Is(Type::String())) { | 8903 if (left_type->Is(Type::String())) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8861 // Inline the string addition into the stub when creating allocation | 8936 // Inline the string addition into the stub when creating allocation |
| 8862 // mementos to gather allocation site feedback. | 8937 // mementos to gather allocation site feedback. |
| 8863 if (graph()->info()->IsStub() && | 8938 if (graph()->info()->IsStub() && |
| 8864 allocation_mode.CreateAllocationMementos()) { | 8939 allocation_mode.CreateAllocationMementos()) { |
| 8865 return BuildStringAdd(left, right, allocation_mode); | 8940 return BuildStringAdd(left, right, allocation_mode); |
| 8866 } | 8941 } |
| 8867 | 8942 |
| 8868 // Register the dependent code with the allocation site. | 8943 // Register the dependent code with the allocation site. |
| 8869 if (!allocation_mode.feedback_site().is_null()) { | 8944 if (!allocation_mode.feedback_site().is_null()) { |
| 8870 ASSERT(!graph()->info()->IsStub()); | 8945 ASSERT(!graph()->info()->IsStub()); |
| 8871 allocation_mode.feedback_site()->AddDependentCompilationInfo( | 8946 Handle<AllocationSite> site(allocation_mode.feedback_site()); |
| 8872 AllocationSite::TENURING, top_info()); | 8947 AllocationSite::AddDependentCompilationInfo( |
| 8948 site, AllocationSite::TENURING, top_info()); |
| 8873 } | 8949 } |
| 8874 | 8950 |
| 8875 // Inline string addition if we know that we'll create a cons string. | 8951 // Inline string addition if we know that we'll create a cons string. |
| 8876 if (left->IsConstant()) { | 8952 if (left->IsConstant()) { |
| 8877 HConstant* c_left = HConstant::cast(left); | 8953 HConstant* c_left = HConstant::cast(left); |
| 8878 if (c_left->HasStringValue()) { | 8954 if (c_left->HasStringValue()) { |
| 8879 int c_left_length = c_left->StringValue()->length(); | 8955 int c_left_length = c_left->StringValue()->length(); |
| 8880 if (c_left_length == 0) { | 8956 if (c_left_length == 0) { |
| 8881 return right; | 8957 return right; |
| 8882 } else if (c_left_length + 1 >= ConsString::kMinLength) { | 8958 } else if (c_left_length + 1 >= ConsString::kMinLength) { |
| (...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9306 Handle<Type> combined_type, | 9382 Handle<Type> combined_type, |
| 9307 int left_position, | 9383 int left_position, |
| 9308 int right_position, | 9384 int right_position, |
| 9309 BailoutId bailout_id) { | 9385 BailoutId bailout_id) { |
| 9310 // Cases handled below depend on collected type feedback. They should | 9386 // Cases handled below depend on collected type feedback. They should |
| 9311 // soft deoptimize when there is no type feedback. | 9387 // soft deoptimize when there is no type feedback. |
| 9312 if (combined_type->Is(Type::None())) { | 9388 if (combined_type->Is(Type::None())) { |
| 9313 Add<HDeoptimize>("Insufficient type feedback for combined type " | 9389 Add<HDeoptimize>("Insufficient type feedback for combined type " |
| 9314 "of binary operation", | 9390 "of binary operation", |
| 9315 Deoptimizer::SOFT); | 9391 Deoptimizer::SOFT); |
| 9316 combined_type = left_type = right_type = handle(Type::Any(), isolate()); | 9392 combined_type = left_type = right_type = Type::Any(isolate()); |
| 9317 } | 9393 } |
| 9318 | 9394 |
| 9319 Representation left_rep = Representation::FromType(left_type); | 9395 Representation left_rep = Representation::FromType(left_type); |
| 9320 Representation right_rep = Representation::FromType(right_type); | 9396 Representation right_rep = Representation::FromType(right_type); |
| 9321 Representation combined_rep = Representation::FromType(combined_type); | 9397 Representation combined_rep = Representation::FromType(combined_type); |
| 9322 | 9398 |
| 9323 if (combined_type->Is(Type::Receiver())) { | 9399 if (combined_type->Is(Type::Receiver())) { |
| 9324 if (Token::IsEqualityOp(op)) { | 9400 if (Token::IsEqualityOp(op)) { |
| 9325 // Can we get away with map check and not instance type check? | 9401 // Can we get away with map check and not instance type check? |
| 9326 HValue* operand_to_check = | 9402 HValue* operand_to_check = |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9403 if (expr->op() == Token::EQ_STRICT) { | 9479 if (expr->op() == Token::EQ_STRICT) { |
| 9404 HConstant* nil_constant = nil == kNullValue | 9480 HConstant* nil_constant = nil == kNullValue |
| 9405 ? graph()->GetConstantNull() | 9481 ? graph()->GetConstantNull() |
| 9406 : graph()->GetConstantUndefined(); | 9482 : graph()->GetConstantUndefined(); |
| 9407 HCompareObjectEqAndBranch* instr = | 9483 HCompareObjectEqAndBranch* instr = |
| 9408 New<HCompareObjectEqAndBranch>(value, nil_constant); | 9484 New<HCompareObjectEqAndBranch>(value, nil_constant); |
| 9409 return ast_context()->ReturnControl(instr, expr->id()); | 9485 return ast_context()->ReturnControl(instr, expr->id()); |
| 9410 } else { | 9486 } else { |
| 9411 ASSERT_EQ(Token::EQ, expr->op()); | 9487 ASSERT_EQ(Token::EQ, expr->op()); |
| 9412 Handle<Type> type = expr->combined_type()->Is(Type::None()) | 9488 Handle<Type> type = expr->combined_type()->Is(Type::None()) |
| 9413 ? handle(Type::Any(), isolate_) | 9489 ? Type::Any(isolate_) : expr->combined_type(); |
| 9414 : expr->combined_type(); | |
| 9415 HIfContinuation continuation; | 9490 HIfContinuation continuation; |
| 9416 BuildCompareNil(value, type, &continuation); | 9491 BuildCompareNil(value, type, &continuation); |
| 9417 return ast_context()->ReturnContinuation(&continuation, expr->id()); | 9492 return ast_context()->ReturnContinuation(&continuation, expr->id()); |
| 9418 } | 9493 } |
| 9419 } | 9494 } |
| 9420 | 9495 |
| 9421 | 9496 |
| 9422 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { | 9497 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { |
| 9423 // If we share optimized code between different closures, the | 9498 // If we share optimized code between different closures, the |
| 9424 // this-function is not a constant, except inside an inlined body. | 9499 // this-function is not a constant, except inside an inlined body. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 9436 AllocationSiteUsageContext* site_context) { | 9511 AllocationSiteUsageContext* site_context) { |
| 9437 NoObservableSideEffectsScope no_effects(this); | 9512 NoObservableSideEffectsScope no_effects(this); |
| 9438 InstanceType instance_type = boilerplate_object->map()->instance_type(); | 9513 InstanceType instance_type = boilerplate_object->map()->instance_type(); |
| 9439 ASSERT(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE); | 9514 ASSERT(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE); |
| 9440 | 9515 |
| 9441 HType type = instance_type == JS_ARRAY_TYPE | 9516 HType type = instance_type == JS_ARRAY_TYPE |
| 9442 ? HType::JSArray() : HType::JSObject(); | 9517 ? HType::JSArray() : HType::JSObject(); |
| 9443 HValue* object_size_constant = Add<HConstant>( | 9518 HValue* object_size_constant = Add<HConstant>( |
| 9444 boilerplate_object->map()->instance_size()); | 9519 boilerplate_object->map()->instance_size()); |
| 9445 | 9520 |
| 9446 // We should pull pre-tenure mode from the allocation site. | |
| 9447 // For now, just see what it says, and remark on it if it sez | |
| 9448 // we should pretenure. That means the rudimentary counting in the garbage | |
| 9449 // collector is having an effect. | |
| 9450 PretenureFlag pretenure_flag = isolate()->heap()->GetPretenureMode(); | 9521 PretenureFlag pretenure_flag = isolate()->heap()->GetPretenureMode(); |
| 9451 if (FLAG_allocation_site_pretenuring) { | 9522 if (FLAG_allocation_site_pretenuring) { |
| 9452 pretenure_flag = site_context->current()->GetPretenureMode() | 9523 pretenure_flag = site_context->current()->GetPretenureMode(); |
| 9453 ? TENURED | 9524 Handle<AllocationSite> site(site_context->current()); |
| 9454 : NOT_TENURED; | 9525 AllocationSite::AddDependentCompilationInfo( |
| 9526 site, AllocationSite::TENURING, top_info()); |
| 9455 } | 9527 } |
| 9456 | 9528 |
| 9457 HInstruction* object = Add<HAllocate>(object_size_constant, type, | 9529 HInstruction* object = Add<HAllocate>(object_size_constant, type, |
| 9458 pretenure_flag, instance_type, site_context->current()); | 9530 pretenure_flag, instance_type, site_context->current()); |
| 9459 | 9531 |
| 9460 BuildEmitObjectHeader(boilerplate_object, object); | 9532 BuildEmitObjectHeader(boilerplate_object, object); |
| 9461 | 9533 |
| 9462 Handle<FixedArrayBase> elements(boilerplate_object->elements()); | 9534 Handle<FixedArrayBase> elements(boilerplate_object->elements()); |
| 9463 int elements_size = (elements->length() > 0 && | 9535 int elements_size = (elements->length() > 0 && |
| 9464 elements->map() != isolate()->heap()->fixed_cow_array_map()) ? | 9536 elements->map() != isolate()->heap()->fixed_cow_array_map()) ? |
| (...skipping 712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10177 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { | 10249 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { |
| 10178 return Bailout(kInlinedRuntimeFunctionGetFromCache); | 10250 return Bailout(kInlinedRuntimeFunctionGetFromCache); |
| 10179 } | 10251 } |
| 10180 | 10252 |
| 10181 | 10253 |
| 10182 // Fast support for number to string. | 10254 // Fast support for number to string. |
| 10183 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { | 10255 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { |
| 10184 ASSERT_EQ(1, call->arguments()->length()); | 10256 ASSERT_EQ(1, call->arguments()->length()); |
| 10185 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 10257 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 10186 HValue* number = Pop(); | 10258 HValue* number = Pop(); |
| 10187 HValue* result = BuildNumberToString( | 10259 HValue* result = BuildNumberToString(number, Type::Number(isolate())); |
| 10188 number, handle(Type::Number(), isolate())); | |
| 10189 return ast_context()->ReturnValue(result); | 10260 return ast_context()->ReturnValue(result); |
| 10190 } | 10261 } |
| 10191 | 10262 |
| 10192 | 10263 |
| 10193 // Fast call for custom callbacks. | 10264 // Fast call for custom callbacks. |
| 10194 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { | 10265 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { |
| 10195 // 1 ~ The function to call is not itself an argument to the call. | 10266 // 1 ~ The function to call is not itself an argument to the call. |
| 10196 int arg_count = call->arguments()->length() - 1; | 10267 int arg_count = call->arguments()->length() - 1; |
| 10197 ASSERT(arg_count >= 1); // There's always at least a receiver. | 10268 ASSERT(arg_count >= 1); // There's always at least a receiver. |
| 10198 | 10269 |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10510 new_env->ClearHistory(); | 10581 new_env->ClearHistory(); |
| 10511 return new_env; | 10582 return new_env; |
| 10512 } | 10583 } |
| 10513 | 10584 |
| 10514 | 10585 |
| 10515 HEnvironment* HEnvironment::CopyForInlining( | 10586 HEnvironment* HEnvironment::CopyForInlining( |
| 10516 Handle<JSFunction> target, | 10587 Handle<JSFunction> target, |
| 10517 int arguments, | 10588 int arguments, |
| 10518 FunctionLiteral* function, | 10589 FunctionLiteral* function, |
| 10519 HConstant* undefined, | 10590 HConstant* undefined, |
| 10520 InliningKind inlining_kind, | 10591 InliningKind inlining_kind) const { |
| 10521 bool undefined_receiver) const { | |
| 10522 ASSERT(frame_type() == JS_FUNCTION); | 10592 ASSERT(frame_type() == JS_FUNCTION); |
| 10523 | 10593 |
| 10524 // Outer environment is a copy of this one without the arguments. | 10594 // Outer environment is a copy of this one without the arguments. |
| 10525 int arity = function->scope()->num_parameters(); | 10595 int arity = function->scope()->num_parameters(); |
| 10526 | 10596 |
| 10527 HEnvironment* outer = Copy(); | 10597 HEnvironment* outer = Copy(); |
| 10528 outer->Drop(arguments + 1); // Including receiver. | 10598 outer->Drop(arguments + 1); // Including receiver. |
| 10529 outer->ClearHistory(); | 10599 outer->ClearHistory(); |
| 10530 | 10600 |
| 10531 if (inlining_kind == CONSTRUCT_CALL_RETURN) { | 10601 if (inlining_kind == CONSTRUCT_CALL_RETURN) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 10549 } | 10619 } |
| 10550 | 10620 |
| 10551 HEnvironment* inner = | 10621 HEnvironment* inner = |
| 10552 new(zone()) HEnvironment(outer, function->scope(), target, zone()); | 10622 new(zone()) HEnvironment(outer, function->scope(), target, zone()); |
| 10553 // Get the argument values from the original environment. | 10623 // Get the argument values from the original environment. |
| 10554 for (int i = 0; i <= arity; ++i) { // Include receiver. | 10624 for (int i = 0; i <= arity; ++i) { // Include receiver. |
| 10555 HValue* push = (i <= arguments) ? | 10625 HValue* push = (i <= arguments) ? |
| 10556 ExpressionStackAt(arguments - i) : undefined; | 10626 ExpressionStackAt(arguments - i) : undefined; |
| 10557 inner->SetValueAt(i, push); | 10627 inner->SetValueAt(i, push); |
| 10558 } | 10628 } |
| 10559 // If the function we are inlining is a strict mode function or a | |
| 10560 // builtin function, pass undefined as the receiver for function | |
| 10561 // calls (instead of the global receiver). | |
| 10562 if (undefined_receiver) { | |
| 10563 inner->SetValueAt(0, undefined); | |
| 10564 } | |
| 10565 inner->SetValueAt(arity + 1, context()); | 10629 inner->SetValueAt(arity + 1, context()); |
| 10566 for (int i = arity + 2; i < inner->length(); ++i) { | 10630 for (int i = arity + 2; i < inner->length(); ++i) { |
| 10567 inner->SetValueAt(i, undefined); | 10631 inner->SetValueAt(i, undefined); |
| 10568 } | 10632 } |
| 10569 | 10633 |
| 10570 inner->set_ast_id(BailoutId::FunctionEntry()); | 10634 inner->set_ast_id(BailoutId::FunctionEntry()); |
| 10571 return inner; | 10635 return inner; |
| 10572 } | 10636 } |
| 10573 | 10637 |
| 10574 | 10638 |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10659 } else { | 10723 } else { |
| 10660 PrintIndent(); | 10724 PrintIndent(); |
| 10661 trace_.Add("successors"); | 10725 trace_.Add("successors"); |
| 10662 for (HSuccessorIterator it(current->end()); !it.Done(); it.Advance()) { | 10726 for (HSuccessorIterator it(current->end()); !it.Done(); it.Advance()) { |
| 10663 trace_.Add(" \"B%d\"", it.Current()->block_id()); | 10727 trace_.Add(" \"B%d\"", it.Current()->block_id()); |
| 10664 } | 10728 } |
| 10665 trace_.Add("\n"); | 10729 trace_.Add("\n"); |
| 10666 } | 10730 } |
| 10667 | 10731 |
| 10668 PrintEmptyProperty("xhandlers"); | 10732 PrintEmptyProperty("xhandlers"); |
| 10669 const char* flags = current->IsLoopSuccessorDominator() | 10733 |
| 10670 ? "dom-loop-succ" | 10734 { |
| 10671 : ""; | 10735 PrintIndent(); |
| 10672 PrintStringProperty("flags", flags); | 10736 trace_.Add("flags"); |
| 10737 if (current->IsLoopSuccessorDominator()) { |
| 10738 trace_.Add(" \"dom-loop-succ\""); |
| 10739 } |
| 10740 if (current->IsUnreachable()) { |
| 10741 trace_.Add(" \"dead\""); |
| 10742 } |
| 10743 if (current->is_osr_entry()) { |
| 10744 trace_.Add(" \"osr\""); |
| 10745 } |
| 10746 trace_.Add("\n"); |
| 10747 } |
| 10673 | 10748 |
| 10674 if (current->dominator() != NULL) { | 10749 if (current->dominator() != NULL) { |
| 10675 PrintBlockProperty("dominator", current->dominator()->block_id()); | 10750 PrintBlockProperty("dominator", current->dominator()->block_id()); |
| 10676 } | 10751 } |
| 10677 | 10752 |
| 10678 PrintIntProperty("loop_depth", current->LoopNestingDepth()); | 10753 PrintIntProperty("loop_depth", current->LoopNestingDepth()); |
| 10679 | 10754 |
| 10680 if (chunk != NULL) { | 10755 if (chunk != NULL) { |
| 10681 int first_index = current->first_instruction_index(); | 10756 int first_index = current->first_instruction_index(); |
| 10682 int last_index = current->last_instruction_index(); | 10757 int last_index = current->last_instruction_index(); |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10910 if (ShouldProduceTraceOutput()) { | 10985 if (ShouldProduceTraceOutput()) { |
| 10911 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 10986 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 10912 } | 10987 } |
| 10913 | 10988 |
| 10914 #ifdef DEBUG | 10989 #ifdef DEBUG |
| 10915 graph_->Verify(false); // No full verify. | 10990 graph_->Verify(false); // No full verify. |
| 10916 #endif | 10991 #endif |
| 10917 } | 10992 } |
| 10918 | 10993 |
| 10919 } } // namespace v8::internal | 10994 } } // namespace v8::internal |
| OLD | NEW |