Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(302)

Side by Side Diff: src/hydrogen.cc

Issue 157543002: A64: Synchronize with r18581. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698