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

Side by Side Diff: src/hydrogen.cc

Issue 145773008: A64: Synchronize with r17104. (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-deoptimizing-mark.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 21 matching lines...) Expand all
32 #include "v8.h" 32 #include "v8.h"
33 #include "codegen.h" 33 #include "codegen.h"
34 #include "full-codegen.h" 34 #include "full-codegen.h"
35 #include "hashmap.h" 35 #include "hashmap.h"
36 #include "hydrogen-bce.h" 36 #include "hydrogen-bce.h"
37 #include "hydrogen-bch.h" 37 #include "hydrogen-bch.h"
38 #include "hydrogen-canonicalize.h" 38 #include "hydrogen-canonicalize.h"
39 #include "hydrogen-check-elimination.h" 39 #include "hydrogen-check-elimination.h"
40 #include "hydrogen-dce.h" 40 #include "hydrogen-dce.h"
41 #include "hydrogen-dehoist.h" 41 #include "hydrogen-dehoist.h"
42 #include "hydrogen-deoptimizing-mark.h"
43 #include "hydrogen-environment-liveness.h" 42 #include "hydrogen-environment-liveness.h"
44 #include "hydrogen-escape-analysis.h" 43 #include "hydrogen-escape-analysis.h"
45 #include "hydrogen-infer-representation.h" 44 #include "hydrogen-infer-representation.h"
46 #include "hydrogen-infer-types.h" 45 #include "hydrogen-infer-types.h"
47 #include "hydrogen-load-elimination.h" 46 #include "hydrogen-load-elimination.h"
48 #include "hydrogen-gvn.h" 47 #include "hydrogen-gvn.h"
49 #include "hydrogen-mark-deoptimize.h" 48 #include "hydrogen-mark-deoptimize.h"
49 #include "hydrogen-mark-unreachable.h"
50 #include "hydrogen-minus-zero.h" 50 #include "hydrogen-minus-zero.h"
51 #include "hydrogen-osr.h" 51 #include "hydrogen-osr.h"
52 #include "hydrogen-range-analysis.h" 52 #include "hydrogen-range-analysis.h"
53 #include "hydrogen-redundant-phi.h" 53 #include "hydrogen-redundant-phi.h"
54 #include "hydrogen-removable-simulates.h" 54 #include "hydrogen-removable-simulates.h"
55 #include "hydrogen-representation-changes.h" 55 #include "hydrogen-representation-changes.h"
56 #include "hydrogen-sce.h" 56 #include "hydrogen-sce.h"
57 #include "hydrogen-uint32-analysis.h" 57 #include "hydrogen-uint32-analysis.h"
58 #include "lithium-allocator.h" 58 #include "lithium-allocator.h"
59 #include "parser.h" 59 #include "parser.h"
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 dominator_(NULL), 91 dominator_(NULL),
92 dominated_blocks_(4, graph->zone()), 92 dominated_blocks_(4, graph->zone()),
93 last_environment_(NULL), 93 last_environment_(NULL),
94 argument_count_(-1), 94 argument_count_(-1),
95 first_instruction_index_(-1), 95 first_instruction_index_(-1),
96 last_instruction_index_(-1), 96 last_instruction_index_(-1),
97 deleted_phis_(4, graph->zone()), 97 deleted_phis_(4, graph->zone()),
98 parent_loop_header_(NULL), 98 parent_loop_header_(NULL),
99 inlined_entry_block_(NULL), 99 inlined_entry_block_(NULL),
100 is_inline_return_target_(false), 100 is_inline_return_target_(false),
101 is_deoptimizing_(false), 101 is_reachable_(true),
102 dominates_loop_successors_(false), 102 dominates_loop_successors_(false),
103 is_osr_entry_(false) { } 103 is_osr_entry_(false) { }
104 104
105 105
106 Isolate* HBasicBlock::isolate() const { 106 Isolate* HBasicBlock::isolate() const {
107 return graph_->isolate(); 107 return graph_->isolate();
108 } 108 }
109 109
110 110
111 void HBasicBlock::MarkUnreachable() {
112 is_reachable_ = false;
113 }
114
115
111 void HBasicBlock::AttachLoopInformation() { 116 void HBasicBlock::AttachLoopInformation() {
112 ASSERT(!IsLoopHeader()); 117 ASSERT(!IsLoopHeader());
113 loop_information_ = new(zone()) HLoopInformation(this, zone()); 118 loop_information_ = new(zone()) HLoopInformation(this, zone());
114 } 119 }
115 120
116 121
117 void HBasicBlock::DetachLoopInformation() { 122 void HBasicBlock::DetachLoopInformation() {
118 ASSERT(IsLoopHeader()); 123 ASSERT(IsLoopHeader());
119 loop_information_ = NULL; 124 loop_information_ = NULL;
120 } 125 }
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 } 211 }
207 212
208 213
209 void HBasicBlock::Goto(HBasicBlock* block, 214 void HBasicBlock::Goto(HBasicBlock* block,
210 FunctionState* state, 215 FunctionState* state,
211 bool add_simulate) { 216 bool add_simulate) {
212 bool drop_extra = state != NULL && 217 bool drop_extra = state != NULL &&
213 state->inlining_kind() == DROP_EXTRA_ON_RETURN; 218 state->inlining_kind() == DROP_EXTRA_ON_RETURN;
214 219
215 if (block->IsInlineReturnTarget()) { 220 if (block->IsInlineReturnTarget()) {
216 AddInstruction(new(zone()) HLeaveInlined()); 221 HEnvironment* env = last_environment();
222 int argument_count = env->arguments_environment()->parameter_count();
223 AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count));
217 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); 224 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
218 } 225 }
219 226
220 if (add_simulate) AddNewSimulate(BailoutId::None()); 227 if (add_simulate) AddNewSimulate(BailoutId::None());
221 HGoto* instr = new(zone()) HGoto(block); 228 HGoto* instr = new(zone()) HGoto(block);
222 Finish(instr); 229 Finish(instr);
223 } 230 }
224 231
225 232
226 void HBasicBlock::AddLeaveInlined(HValue* return_value, 233 void HBasicBlock::AddLeaveInlined(HValue* return_value,
227 FunctionState* state) { 234 FunctionState* state) {
228 HBasicBlock* target = state->function_return(); 235 HBasicBlock* target = state->function_return();
229 bool drop_extra = state->inlining_kind() == DROP_EXTRA_ON_RETURN; 236 bool drop_extra = state->inlining_kind() == DROP_EXTRA_ON_RETURN;
230 237
231 ASSERT(target->IsInlineReturnTarget()); 238 ASSERT(target->IsInlineReturnTarget());
232 ASSERT(return_value != NULL); 239 ASSERT(return_value != NULL);
233 AddInstruction(new(zone()) HLeaveInlined()); 240 HEnvironment* env = last_environment();
241 int argument_count = env->arguments_environment()->parameter_count();
242 AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count));
234 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); 243 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
235 last_environment()->Push(return_value); 244 last_environment()->Push(return_value);
236 AddNewSimulate(BailoutId::None()); 245 AddNewSimulate(BailoutId::None());
237 HGoto* instr = new(zone()) HGoto(target); 246 HGoto* instr = new(zone()) HGoto(target);
238 Finish(instr); 247 Finish(instr);
239 } 248 }
240 249
241 250
242 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) { 251 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
243 ASSERT(!HasEnvironment()); 252 ASSERT(!HasEnvironment());
(...skipping 2034 matching lines...) Expand 10 before | Expand all | Expand 10 after
2278 entry_block_(NULL), 2287 entry_block_(NULL),
2279 blocks_(8, info->zone()), 2288 blocks_(8, info->zone()),
2280 values_(16, info->zone()), 2289 values_(16, info->zone()),
2281 phi_list_(NULL), 2290 phi_list_(NULL),
2282 uint32_instructions_(NULL), 2291 uint32_instructions_(NULL),
2283 osr_(NULL), 2292 osr_(NULL),
2284 info_(info), 2293 info_(info),
2285 zone_(info->zone()), 2294 zone_(info->zone()),
2286 is_recursive_(false), 2295 is_recursive_(false),
2287 use_optimistic_licm_(false), 2296 use_optimistic_licm_(false),
2288 has_soft_deoptimize_(false),
2289 depends_on_empty_array_proto_elements_(false), 2297 depends_on_empty_array_proto_elements_(false),
2290 type_change_checksum_(0), 2298 type_change_checksum_(0),
2291 maximum_environment_size_(0), 2299 maximum_environment_size_(0),
2292 no_side_effects_scope_count_(0) { 2300 no_side_effects_scope_count_(0) {
2293 if (info->IsStub()) { 2301 if (info->IsStub()) {
2294 HydrogenCodeStub* stub = info->code_stub(); 2302 HydrogenCodeStub* stub = info->code_stub();
2295 CodeStubInterfaceDescriptor* descriptor = 2303 CodeStubInterfaceDescriptor* descriptor =
2296 stub->GetInterfaceDescriptor(isolate_); 2304 stub->GetInterfaceDescriptor(isolate_);
2297 start_environment_ = 2305 start_environment_ =
2298 new(zone_) HEnvironment(zone_, descriptor->environment_length()); 2306 new(zone_) HEnvironment(zone_, descriptor->environment_length());
(...skipping 826 matching lines...) Expand 10 before | Expand all | Expand 10 after
3125 3133
3126 #ifdef DEBUG 3134 #ifdef DEBUG
3127 // Do a full verify after building the graph and computing dominators. 3135 // Do a full verify after building the graph and computing dominators.
3128 Verify(true); 3136 Verify(true);
3129 #endif 3137 #endif
3130 3138
3131 if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) { 3139 if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) {
3132 Run<HEnvironmentLivenessAnalysisPhase>(); 3140 Run<HEnvironmentLivenessAnalysisPhase>();
3133 } 3141 }
3134 3142
3135 Run<HPropagateDeoptimizingMarkPhase>();
3136 if (!CheckConstPhiUses()) { 3143 if (!CheckConstPhiUses()) {
3137 *bailout_reason = kUnsupportedPhiUseOfConstVariable; 3144 *bailout_reason = kUnsupportedPhiUseOfConstVariable;
3138 return false; 3145 return false;
3139 } 3146 }
3140 Run<HRedundantPhiEliminationPhase>(); 3147 Run<HRedundantPhiEliminationPhase>();
3141 if (!CheckArgumentsPhiUses()) { 3148 if (!CheckArgumentsPhiUses()) {
3142 *bailout_reason = kUnsupportedPhiUseOfArguments; 3149 *bailout_reason = kUnsupportedPhiUseOfArguments;
3143 return false; 3150 return false;
3144 } 3151 }
3145 3152
3153 // Find and mark unreachable code to simplify optimizations, especially gvn,
3154 // where unreachable code could unnecessarily defeat LICM.
3155 Run<HMarkUnreachableBlocksPhase>();
3156
3146 if (FLAG_check_elimination) Run<HCheckEliminationPhase>(); 3157 if (FLAG_check_elimination) Run<HCheckEliminationPhase>();
3147 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); 3158 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
3148 if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>(); 3159 if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>();
3149 3160
3150 if (FLAG_load_elimination) Run<HLoadEliminationPhase>(); 3161 if (FLAG_load_elimination) Run<HLoadEliminationPhase>();
3151 3162
3152 CollectPhis(); 3163 CollectPhis();
3153 3164
3154 if (has_osr()) osr()->FinishOsrValues(); 3165 if (has_osr()) osr()->FinishOsrValues();
3155 3166
(...skipping 26 matching lines...) Expand all
3182 // Eliminate redundant stack checks on backwards branches. 3193 // Eliminate redundant stack checks on backwards branches.
3183 Run<HStackCheckEliminationPhase>(); 3194 Run<HStackCheckEliminationPhase>();
3184 3195
3185 if (FLAG_array_bounds_checks_elimination) Run<HBoundsCheckEliminationPhase>(); 3196 if (FLAG_array_bounds_checks_elimination) Run<HBoundsCheckEliminationPhase>();
3186 if (FLAG_array_bounds_checks_hoisting) Run<HBoundsCheckHoistingPhase>(); 3197 if (FLAG_array_bounds_checks_hoisting) Run<HBoundsCheckHoistingPhase>();
3187 if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>(); 3198 if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>();
3188 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); 3199 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
3189 3200
3190 RestoreActualValues(); 3201 RestoreActualValues();
3191 3202
3203 // Find unreachable code a second time, GVN and other optimizations may have
3204 // made blocks unreachable that were previously reachable.
3205 Run<HMarkUnreachableBlocksPhase>();
3206
3192 return true; 3207 return true;
3193 } 3208 }
3194 3209
3195 3210
3196 void HGraph::RestoreActualValues() { 3211 void HGraph::RestoreActualValues() {
3197 HPhase phase("H_Restore actual values", this); 3212 HPhase phase("H_Restore actual values", this);
3198 3213
3199 for (int block_index = 0; block_index < blocks()->length(); block_index++) { 3214 for (int block_index = 0; block_index < blocks()->length(); block_index++) {
3200 HBasicBlock* block = blocks()->at(block_index); 3215 HBasicBlock* block = blocks()->at(block_index);
3201 3216
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after
3616 3631
3617 // Identify the block where normal (non-fall-through) control flow 3632 // Identify the block where normal (non-fall-through) control flow
3618 // goes to. 3633 // goes to.
3619 HBasicBlock* normal_block = NULL; 3634 HBasicBlock* normal_block = NULL;
3620 if (clause->is_default()) { 3635 if (clause->is_default()) {
3621 if (last_block != NULL) { 3636 if (last_block != NULL) {
3622 normal_block = last_block; 3637 normal_block = last_block;
3623 last_block = NULL; // Cleared to indicate we've handled it. 3638 last_block = NULL; // Cleared to indicate we've handled it.
3624 } 3639 }
3625 } else { 3640 } else {
3641 // If the current test block is deoptimizing due to an unhandled clause
3642 // of the switch, the test instruction is in the next block since the
3643 // deopt must end the current block.
3644 if (curr_test_block->IsDeoptimizing()) {
3645 ASSERT(curr_test_block->end()->SecondSuccessor() == NULL);
3646 curr_test_block = curr_test_block->end()->FirstSuccessor();
3647 }
3626 normal_block = curr_test_block->end()->FirstSuccessor(); 3648 normal_block = curr_test_block->end()->FirstSuccessor();
3627 curr_test_block = curr_test_block->end()->SecondSuccessor(); 3649 curr_test_block = curr_test_block->end()->SecondSuccessor();
3628 } 3650 }
3629 3651
3630 // Identify a block to emit the body into. 3652 // Identify a block to emit the body into.
3631 if (normal_block == NULL) { 3653 if (normal_block == NULL) {
3632 if (fall_through_block == NULL) { 3654 if (fall_through_block == NULL) {
3633 // (a) Unreachable. 3655 // (a) Unreachable.
3634 if (clause->is_default()) { 3656 if (clause->is_default()) {
3635 continue; // Might still be reachable clause bodies. 3657 continue; // Might still be reachable clause bodies.
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
3978 shared_info = Compiler::BuildFunctionInfo(expr, current_info()->script()); 4000 shared_info = Compiler::BuildFunctionInfo(expr, current_info()->script());
3979 } 4001 }
3980 // We also have a stack overflow if the recursive compilation did. 4002 // We also have a stack overflow if the recursive compilation did.
3981 if (HasStackOverflow()) return; 4003 if (HasStackOverflow()) return;
3982 HFunctionLiteral* instr = 4004 HFunctionLiteral* instr =
3983 New<HFunctionLiteral>(shared_info, expr->pretenure()); 4005 New<HFunctionLiteral>(shared_info, expr->pretenure());
3984 return ast_context()->ReturnInstruction(instr, expr->id()); 4006 return ast_context()->ReturnInstruction(instr, expr->id());
3985 } 4007 }
3986 4008
3987 4009
3988 void HOptimizedGraphBuilder::VisitSharedFunctionInfoLiteral( 4010 void HOptimizedGraphBuilder::VisitNativeFunctionLiteral(
3989 SharedFunctionInfoLiteral* expr) { 4011 NativeFunctionLiteral* expr) {
3990 ASSERT(!HasStackOverflow()); 4012 ASSERT(!HasStackOverflow());
3991 ASSERT(current_block() != NULL); 4013 ASSERT(current_block() != NULL);
3992 ASSERT(current_block()->HasPredecessor()); 4014 ASSERT(current_block()->HasPredecessor());
3993 return Bailout(kSharedFunctionInfoLiteral); 4015 return Bailout(kNativeFunctionLiteral);
3994 } 4016 }
3995 4017
3996 4018
3997 void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) { 4019 void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) {
3998 ASSERT(!HasStackOverflow()); 4020 ASSERT(!HasStackOverflow());
3999 ASSERT(current_block() != NULL); 4021 ASSERT(current_block() != NULL);
4000 ASSERT(current_block()->HasPredecessor()); 4022 ASSERT(current_block()->HasPredecessor());
4001 HBasicBlock* cond_true = graph()->CreateBasicBlock(); 4023 HBasicBlock* cond_true = graph()->CreateBasicBlock();
4002 HBasicBlock* cond_false = graph()->CreateBasicBlock(); 4024 HBasicBlock* cond_false = graph()->CreateBasicBlock();
4003 CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false)); 4025 CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false));
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
4316 // Check whether to use fast or slow deep-copying for boilerplate. 4338 // Check whether to use fast or slow deep-copying for boilerplate.
4317 int max_properties = kMaxFastLiteralProperties; 4339 int max_properties = kMaxFastLiteralProperties;
4318 Handle<Object> boilerplate(closure->literals()->get( 4340 Handle<Object> boilerplate(closure->literals()->get(
4319 expr->literal_index()), isolate()); 4341 expr->literal_index()), isolate());
4320 if (boilerplate->IsJSObject() && 4342 if (boilerplate->IsJSObject() &&
4321 IsFastLiteral(Handle<JSObject>::cast(boilerplate), 4343 IsFastLiteral(Handle<JSObject>::cast(boilerplate),
4322 kMaxFastLiteralDepth, 4344 kMaxFastLiteralDepth,
4323 &max_properties)) { 4345 &max_properties)) {
4324 Handle<JSObject> boilerplate_object = Handle<JSObject>::cast(boilerplate); 4346 Handle<JSObject> boilerplate_object = Handle<JSObject>::cast(boilerplate);
4325 4347
4326 literal = BuildFastLiteral(boilerplate_object, 4348 literal = BuildFastLiteral(boilerplate_object);
4327 Handle<Object>::null(),
4328 DONT_TRACK_ALLOCATION_SITE);
4329 } else { 4349 } else {
4330 NoObservableSideEffectsScope no_effects(this); 4350 NoObservableSideEffectsScope no_effects(this);
4331 Handle<FixedArray> closure_literals(closure->literals(), isolate()); 4351 Handle<FixedArray> closure_literals(closure->literals(), isolate());
4332 Handle<FixedArray> constant_properties = expr->constant_properties(); 4352 Handle<FixedArray> constant_properties = expr->constant_properties();
4333 int literal_index = expr->literal_index(); 4353 int literal_index = expr->literal_index();
4334 int flags = expr->fast_elements() 4354 int flags = expr->fast_elements()
4335 ? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags; 4355 ? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags;
4336 flags |= expr->has_function() 4356 flags |= expr->has_function()
4337 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags; 4357 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags;
4338 4358
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
4462 ElementsKind boilerplate_elements_kind = 4482 ElementsKind boilerplate_elements_kind =
4463 Handle<JSObject>::cast(boilerplate_object)->GetElementsKind(); 4483 Handle<JSObject>::cast(boilerplate_object)->GetElementsKind();
4464 4484
4465 ASSERT(AllocationSite::CanTrack(boilerplate_object->map()->instance_type())); 4485 ASSERT(AllocationSite::CanTrack(boilerplate_object->map()->instance_type()));
4466 4486
4467 // Check whether to use fast or slow deep-copying for boilerplate. 4487 // Check whether to use fast or slow deep-copying for boilerplate.
4468 int max_properties = kMaxFastLiteralProperties; 4488 int max_properties = kMaxFastLiteralProperties;
4469 if (IsFastLiteral(boilerplate_object, 4489 if (IsFastLiteral(boilerplate_object,
4470 kMaxFastLiteralDepth, 4490 kMaxFastLiteralDepth,
4471 &max_properties)) { 4491 &max_properties)) {
4472 // TODO(mvstanton): This heuristic is only a temporary solution. In the 4492 literal = BuildFastLiteral(boilerplate_object);
4473 // end, we want to quit creating allocation site info after a certain number
4474 // of GCs for a call site.
4475 AllocationSiteMode mode = AllocationSite::GetMode(
4476 boilerplate_elements_kind);
4477
4478 // it doesn't make sense to create allocation mementos if we are going to
4479 // create in old space.
4480 if (mode == TRACK_ALLOCATION_SITE &&
4481 isolate()->heap()->GetPretenureMode() == TENURED) {
4482 mode = DONT_TRACK_ALLOCATION_SITE;
4483 }
4484
4485 literal = BuildFastLiteral(boilerplate_object,
4486 site,
4487 mode);
4488 } else { 4493 } else {
4489 NoObservableSideEffectsScope no_effects(this); 4494 NoObservableSideEffectsScope no_effects(this);
4490 // Boilerplate already exists and constant elements are never accessed, 4495 // Boilerplate already exists and constant elements are never accessed,
4491 // pass an empty fixed array to the runtime function instead. 4496 // pass an empty fixed array to the runtime function instead.
4492 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); 4497 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array();
4493 int literal_index = expr->literal_index(); 4498 int literal_index = expr->literal_index();
4494 4499
4495 Add<HPushArgument>(Add<HConstant>(literals)); 4500 Add<HPushArgument>(Add<HConstant>(literals));
4496 Add<HPushArgument>(Add<HConstant>(literal_index)); 4501 Add<HPushArgument>(Add<HConstant>(literal_index));
4497 Add<HPushArgument>(Add<HConstant>(constants)); 4502 Add<HPushArgument>(Add<HConstant>(constants));
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
4547 } 4552 }
4548 4553
4549 Add<HSimulate>(expr->GetIdForElement(i)); 4554 Add<HSimulate>(expr->GetIdForElement(i));
4550 } 4555 }
4551 4556
4552 Drop(1); // array literal index 4557 Drop(1); // array literal index
4553 return ast_context()->ReturnValue(Pop()); 4558 return ast_context()->ReturnValue(Pop());
4554 } 4559 }
4555 4560
4556 4561
4557 // Sets the lookup result and returns true if the load/store can be inlined.
4558 static bool ComputeLoadStoreField(Handle<Map> type,
4559 Handle<String> name,
4560 LookupResult* lookup,
4561 bool is_store) {
4562 ASSERT(!is_store || !type->is_observed());
4563 if (!CanInlinePropertyAccess(*type)) {
4564 lookup->NotFound();
4565 return false;
4566 }
4567 // If we directly find a field, the access can be inlined.
4568 type->LookupDescriptor(NULL, *name, lookup);
4569 if (lookup->IsField()) return true;
4570
4571 // For a load, we are out of luck if there is no such field.
4572 if (!is_store) return false;
4573
4574 // 2nd chance: A store into a non-existent field can still be inlined if we
4575 // have a matching transition and some room left in the object.
4576 type->LookupTransition(NULL, *name, lookup);
4577 return lookup->IsTransitionToField(*type) &&
4578 (type->unused_property_fields() > 0);
4579 }
4580
4581
4582 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object, 4562 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object,
4583 Handle<Map> map) { 4563 Handle<Map> map) {
4584 BuildCheckHeapObject(object); 4564 BuildCheckHeapObject(object);
4585 return Add<HCheckMaps>(object, map, top_info()); 4565 return Add<HCheckMaps>(object, map, top_info());
4586 } 4566 }
4587 4567
4588 4568
4589 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( 4569 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
4590 HValue* checked_object, 4570 HValue* checked_object,
4591 Handle<String> name, 4571 Handle<String> name,
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
4677 HValue* context = environment()->context(); 4657 HValue* context = environment()->context();
4678 return new(zone()) HStoreNamedGeneric( 4658 return new(zone()) HStoreNamedGeneric(
4679 context, 4659 context,
4680 object, 4660 object,
4681 name, 4661 name,
4682 value, 4662 value,
4683 function_strict_mode_flag()); 4663 function_strict_mode_flag());
4684 } 4664 }
4685 4665
4686 4666
4667 // Sets the lookup result and returns true if the load/store can be inlined.
4668 static bool ComputeStoreField(Handle<Map> type,
4669 Handle<String> name,
4670 LookupResult* lookup,
4671 bool lookup_transition = true) {
4672 ASSERT(!type->is_observed());
4673 if (!CanInlinePropertyAccess(*type)) {
4674 lookup->NotFound();
4675 return false;
4676 }
4677 // If we directly find a field, the access can be inlined.
4678 type->LookupDescriptor(NULL, *name, lookup);
4679 if (lookup->IsField()) return true;
4680
4681 if (!lookup_transition) return false;
4682
4683 type->LookupTransition(NULL, *name, lookup);
4684 return lookup->IsTransitionToField(*type) &&
4685 (type->unused_property_fields() > 0);
4686 }
4687
4688
4687 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic( 4689 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic(
4688 HValue* object, 4690 HValue* object,
4689 Handle<String> name, 4691 Handle<String> name,
4690 HValue* value, 4692 HValue* value,
4691 Handle<Map> map) { 4693 Handle<Map> map) {
4692 // Handle a store to a known field. 4694 // Handle a store to a known field.
4693 LookupResult lookup(isolate()); 4695 LookupResult lookup(isolate());
4694 if (ComputeLoadStoreField(map, name, &lookup, true)) { 4696 if (ComputeStoreField(map, name, &lookup)) {
4695 HCheckMaps* checked_object = AddCheckMap(object, map); 4697 HCheckMaps* checked_object = AddCheckMap(object, map);
4696 return BuildStoreNamedField(checked_object, name, value, map, &lookup); 4698 return BuildStoreNamedField(checked_object, name, value, map, &lookup);
4697 } 4699 }
4698 4700
4699 // No luck, do a generic store. 4701 // No luck, do a generic store.
4700 return BuildStoreNamedGeneric(object, name, value); 4702 return BuildStoreNamedGeneric(object, name, value);
4701 } 4703 }
4702 4704
4703 4705
4704 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatibleForLoad( 4706 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatibleForLoad(
4705 PropertyAccessInfo* info) { 4707 PropertyAccessInfo* info) {
4706 if (!CanInlinePropertyAccess(*map_)) return false; 4708 if (!CanInlinePropertyAccess(*map_)) return false;
4707 4709
4708 if (!LookupDescriptor()) return false; 4710 if (!LookupDescriptor()) return false;
4709 4711
4710 if (!lookup_.IsFound()) { 4712 if (!lookup_.IsFound()) {
4711 return (!info->lookup_.IsFound() || !info->holder_.is_null()) && 4713 return (!info->lookup_.IsFound() || info->has_holder()) &&
4712 map_->prototype() == info->map_->prototype(); 4714 map_->prototype() == info->map_->prototype();
4713 } 4715 }
4714 4716
4717 // Mismatch if the other access info found the property in the prototype
4718 // chain.
4719 if (info->has_holder()) return false;
4720
4715 if (lookup_.IsPropertyCallbacks()) { 4721 if (lookup_.IsPropertyCallbacks()) {
4716 return accessor_.is_identical_to(info->accessor_); 4722 return accessor_.is_identical_to(info->accessor_);
4717 } 4723 }
4718 4724
4719 if (lookup_.IsConstant()) { 4725 if (lookup_.IsConstant()) {
4720 return constant_.is_identical_to(info->constant_); 4726 return constant_.is_identical_to(info->constant_);
4721 } 4727 }
4722 4728
4723 ASSERT(lookup_.IsField()); 4729 ASSERT(lookup_.IsField());
4724 if (!info->lookup_.IsField()) return false; 4730 if (!info->lookup_.IsField()) return false;
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
4950 // for all maps. Requires special map check on the set of all handled maps. 4956 // for all maps. Requires special map check on the set of all handled maps.
4951 if (types->length() > kMaxStorePolymorphism) return false; 4957 if (types->length() > kMaxStorePolymorphism) return false;
4952 4958
4953 LookupResult lookup(isolate()); 4959 LookupResult lookup(isolate());
4954 int count; 4960 int count;
4955 Representation representation = Representation::None(); 4961 Representation representation = Representation::None();
4956 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. 4962 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused.
4957 for (count = 0; count < types->length(); ++count) { 4963 for (count = 0; count < types->length(); ++count) {
4958 Handle<Map> map = types->at(count); 4964 Handle<Map> map = types->at(count);
4959 // Pass false to ignore transitions. 4965 // Pass false to ignore transitions.
4960 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; 4966 if (!ComputeStoreField(map, name, &lookup, false)) break;
4961 ASSERT(!map->is_observed()); 4967 ASSERT(!map->is_observed());
4962 4968
4963 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); 4969 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name);
4964 Representation new_representation = new_access.representation(); 4970 Representation new_representation = new_access.representation();
4965 4971
4966 if (count == 0) { 4972 if (count == 0) {
4967 // First time through the loop; set access and representation. 4973 // First time through the loop; set access and representation.
4968 access = new_access; 4974 access = new_access;
4969 representation = new_representation; 4975 representation = new_representation;
4970 } else if (!representation.IsCompatibleForStore(new_representation)) { 4976 } else if (!representation.IsCompatibleForStore(new_representation)) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
5012 } 5018 }
5013 5019
5014 // TODO(ager): We should recognize when the prototype chains for different 5020 // TODO(ager): We should recognize when the prototype chains for different
5015 // maps are identical. In that case we can avoid repeatedly generating the 5021 // maps are identical. In that case we can avoid repeatedly generating the
5016 // same prototype map checks. 5022 // same prototype map checks.
5017 int count = 0; 5023 int count = 0;
5018 HBasicBlock* join = NULL; 5024 HBasicBlock* join = NULL;
5019 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { 5025 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) {
5020 Handle<Map> map = types->at(i); 5026 Handle<Map> map = types->at(i);
5021 LookupResult lookup(isolate()); 5027 LookupResult lookup(isolate());
5022 if (ComputeLoadStoreField(map, name, &lookup, true)) { 5028 if (ComputeStoreField(map, name, &lookup)) {
5023 if (count == 0) { 5029 if (count == 0) {
5024 BuildCheckHeapObject(object); 5030 BuildCheckHeapObject(object);
5025 join = graph()->CreateBasicBlock(); 5031 join = graph()->CreateBasicBlock();
5026 } 5032 }
5027 ++count; 5033 ++count;
5028 HBasicBlock* if_true = graph()->CreateBasicBlock(); 5034 HBasicBlock* if_true = graph()->CreateBasicBlock();
5029 HBasicBlock* if_false = graph()->CreateBasicBlock(); 5035 HBasicBlock* if_false = graph()->CreateBasicBlock();
5030 HCompareMap* compare = New<HCompareMap>(object, map, if_true, if_false); 5036 HCompareMap* compare = New<HCompareMap>(object, map, if_true, if_false);
5031 current_block()->Finish(compare); 5037 current_block()->Finish(compare);
5032 5038
(...skipping 1345 matching lines...) Expand 10 before | Expand all | Expand 10 after
6378 int nodes_added = InliningAstSize(target); 6384 int nodes_added = InliningAstSize(target);
6379 if (nodes_added == kNotInlinable) return false; 6385 if (nodes_added == kNotInlinable) return false;
6380 6386
6381 Handle<JSFunction> caller = current_info()->closure(); 6387 Handle<JSFunction> caller = current_info()->closure();
6382 6388
6383 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { 6389 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
6384 TraceInline(target, caller, "target AST is too large [early]"); 6390 TraceInline(target, caller, "target AST is too large [early]");
6385 return false; 6391 return false;
6386 } 6392 }
6387 6393
6388 #if !V8_TARGET_ARCH_IA32 6394 #if !V8_TARGET_ARCH_IA32 && !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_MIPS
6389 // Target must be able to use caller's context. 6395 // Target must be able to use caller's context.
6390 CompilationInfo* outer_info = current_info(); 6396 CompilationInfo* outer_info = current_info();
6391 if (target->context() != outer_info->closure()->context() || 6397 if (target->context() != outer_info->closure()->context() ||
6392 outer_info->scope()->contains_with() || 6398 outer_info->scope()->contains_with() ||
6393 outer_info->scope()->num_heap_slots() > 0) { 6399 outer_info->scope()->num_heap_slots() > 0) {
6394 TraceInline(target, caller, "target requires context change"); 6400 TraceInline(target, caller, "target requires context change");
6395 return false; 6401 return false;
6396 } 6402 }
6397 #endif 6403 #endif
6398 6404
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
6527 HConstant* undefined = graph()->GetConstantUndefined(); 6533 HConstant* undefined = graph()->GetConstantUndefined();
6528 bool undefined_receiver = HEnvironment::UseUndefinedReceiver( 6534 bool undefined_receiver = HEnvironment::UseUndefinedReceiver(
6529 target, function, call_kind, inlining_kind); 6535 target, function, call_kind, inlining_kind);
6530 HEnvironment* inner_env = 6536 HEnvironment* inner_env =
6531 environment()->CopyForInlining(target, 6537 environment()->CopyForInlining(target,
6532 arguments_count, 6538 arguments_count,
6533 function, 6539 function,
6534 undefined, 6540 undefined,
6535 function_state()->inlining_kind(), 6541 function_state()->inlining_kind(),
6536 undefined_receiver); 6542 undefined_receiver);
6537 #if V8_TARGET_ARCH_IA32 6543 #if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
6538 // IA32 only, overwrite the caller's context in the deoptimization 6544 // IA32, ARM and MIPS only, overwrite the caller's context in the
6539 // environment with the correct one. 6545 // deoptimization environment with the correct one.
6540 // 6546 //
6541 // TODO(kmillikin): implement the same inlining on other platforms so we 6547 // TODO(kmillikin): implement the same inlining on other platforms so we
6542 // can remove the unsightly ifdefs in this function. 6548 // can remove the unsightly ifdefs in this function.
6543 HConstant* context = Add<HConstant>(Handle<Context>(target->context())); 6549 HConstant* context = Add<HConstant>(Handle<Context>(target->context()));
6544 inner_env->BindContext(context); 6550 inner_env->BindContext(context);
6545 #endif 6551 #endif
6546 6552
6547 Add<HSimulate>(return_id); 6553 Add<HSimulate>(return_id);
6548 current_block()->UpdateEnvironment(inner_env); 6554 current_block()->UpdateEnvironment(inner_env);
6549 HArgumentsObject* arguments_object = NULL; 6555 HArgumentsObject* arguments_object = NULL;
(...skipping 963 matching lines...) Expand 10 before | Expand all | Expand 10 after
7513 CreateJoin(materialize_false, materialize_true, expr->id()); 7519 CreateJoin(materialize_false, materialize_true, expr->id());
7514 set_current_block(join); 7520 set_current_block(join);
7515 if (join != NULL) return ast_context()->ReturnValue(Pop()); 7521 if (join != NULL) return ast_context()->ReturnValue(Pop());
7516 } 7522 }
7517 7523
7518 7524
7519 HInstruction* HOptimizedGraphBuilder::BuildIncrement( 7525 HInstruction* HOptimizedGraphBuilder::BuildIncrement(
7520 bool returns_original_input, 7526 bool returns_original_input,
7521 CountOperation* expr) { 7527 CountOperation* expr) {
7522 // The input to the count operation is on top of the expression stack. 7528 // The input to the count operation is on top of the expression stack.
7523 TypeInfo info = expr->type(); 7529 Handle<Type> info = expr->type();
7524 Representation rep = Representation::FromType(info); 7530 Representation rep = Representation::FromType(info);
7525 if (rep.IsNone() || rep.IsTagged()) { 7531 if (rep.IsNone() || rep.IsTagged()) {
7526 rep = Representation::Smi(); 7532 rep = Representation::Smi();
7527 } 7533 }
7528 7534
7529 if (returns_original_input) { 7535 if (returns_original_input) {
7530 // We need an explicit HValue representing ToNumber(input). The 7536 // We need an explicit HValue representing ToNumber(input). The
7531 // actual HChange instruction we need is (sometimes) added in a later 7537 // actual HChange instruction we need is (sometimes) added in a later
7532 // phase, so it is not available now to be used as an input to HAdd and 7538 // phase, so it is not available now to be used as an input to HAdd and
7533 // as the return value. 7539 // as the return value.
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
7817 return value; 7823 return value;
7818 } 7824 }
7819 7825
7820 if (expected_obj->Is(Type::Undefined())) { 7826 if (expected_obj->Is(Type::Undefined())) {
7821 // This is already done by HChange. 7827 // This is already done by HChange.
7822 *expected = handle(Type::Union( 7828 *expected = handle(Type::Union(
7823 expected_number, handle(Type::Double(), isolate())), isolate()); 7829 expected_number, handle(Type::Double(), isolate())), isolate());
7824 return value; 7830 return value;
7825 } 7831 }
7826 7832
7827 if (expected_obj->Is(Type::Null())) {
7828 *expected = handle(Type::Union(
7829 expected_number, handle(Type::Smi(), isolate())), isolate());
7830 IfBuilder if_null(this);
7831 if_null.If<HCompareObjectEqAndBranch>(value,
7832 graph()->GetConstantNull());
7833 if_null.Then();
7834 Push(graph()->GetConstant0());
7835 if_null.Else();
7836 Push(value);
7837 if_null.End();
7838 return Pop();
7839 }
7840
7841 if (expected_obj->Is(Type::Boolean())) {
7842 *expected = handle(Type::Union(
7843 expected_number, handle(Type::Smi(), isolate())), isolate());
7844 IfBuilder if_true(this);
7845 if_true.If<HCompareObjectEqAndBranch>(value,
7846 graph()->GetConstantTrue());
7847 if_true.Then();
7848 Push(graph()->GetConstant1());
7849 if_true.Else();
7850 IfBuilder if_false(this);
7851 if_false.If<HCompareObjectEqAndBranch>(value,
7852 graph()->GetConstantFalse());
7853 if_false.Then();
7854 Push(graph()->GetConstant0());
7855 if_false.Else();
7856 Push(value);
7857 if_false.End();
7858 if_true.End();
7859 return Pop();
7860 }
7861
7862 return value; 7833 return value;
7863 } 7834 }
7864 7835
7865 7836
7866 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( 7837 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation(
7867 BinaryOperation* expr, 7838 BinaryOperation* expr,
7868 HValue* left, 7839 HValue* left,
7869 HValue* right) { 7840 HValue* right) {
7870 Handle<Type> left_type = expr->left()->bounds().lower; 7841 Handle<Type> left_type = expr->left()->bounds().lower;
7871 Handle<Type> right_type = expr->right()->bounds().lower; 7842 Handle<Type> right_type = expr->right()->bounds().lower;
7872 Handle<Type> result_type = expr->bounds().lower; 7843 Handle<Type> result_type = expr->bounds().lower;
7873 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); 7844 Maybe<int> fixed_right_arg = expr->fixed_right_arg();
7874 7845
7875 return HGraphBuilder::BuildBinaryOperation(expr->op(), left, right, 7846 return HGraphBuilder::BuildBinaryOperation(expr->op(), left, right,
7876 left_type, right_type, result_type, fixed_right_arg); 7847 left_type, right_type, result_type, fixed_right_arg);
7877 } 7848 }
7878 7849
7879 7850
7880 HInstruction* HGraphBuilder::BuildBinaryOperation( 7851 HInstruction* HGraphBuilder::BuildBinaryOperation(
7881 Token::Value op, 7852 Token::Value op,
7882 HValue* left, 7853 HValue* left,
7883 HValue* right, 7854 HValue* right,
7884 Handle<Type> left_type, 7855 Handle<Type> left_type,
7885 Handle<Type> right_type, 7856 Handle<Type> right_type,
7886 Handle<Type> result_type, 7857 Handle<Type> result_type,
7887 Maybe<int> fixed_right_arg) { 7858 Maybe<int> fixed_right_arg,
7859 bool binop_stub) {
7888 7860
7889 Representation left_rep = Representation::FromType(left_type); 7861 Representation left_rep = Representation::FromType(left_type);
7890 Representation right_rep = Representation::FromType(right_type); 7862 Representation right_rep = Representation::FromType(right_type);
7891 7863
7892 bool maybe_string_add = op == Token::ADD && 7864 bool maybe_string_add = op == Token::ADD &&
7893 (left_type->Maybe(Type::String()) || 7865 (left_type->Maybe(Type::String()) ||
7894 right_type->Maybe(Type::String())); 7866 right_type->Maybe(Type::String()));
7895 7867
7896 if (left_type->Is(Type::None())) { 7868 if (left_type->Is(Type::None())) {
7897 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", 7869 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation",
7898 Deoptimizer::SOFT); 7870 Deoptimizer::SOFT);
7899 // TODO(rossberg): we should be able to get rid of non-continuous 7871 // TODO(rossberg): we should be able to get rid of non-continuous
7900 // defaults. 7872 // defaults.
7901 left_type = handle(Type::Any(), isolate()); 7873 left_type = handle(Type::Any(), isolate());
7902 } else { 7874 } else {
7903 if (!maybe_string_add) left = TruncateToNumber(left, &left_type); 7875 if (!maybe_string_add) left = TruncateToNumber(left, &left_type);
7904 left_rep = Representation::FromType(left_type); 7876 left_rep = Representation::FromType(left_type);
7905 } 7877 }
7906 7878
7907 if (right_type->Is(Type::None())) { 7879 if (right_type->Is(Type::None())) {
7908 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", 7880 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation",
7909 Deoptimizer::SOFT); 7881 Deoptimizer::SOFT);
7910 right_type = handle(Type::Any(), isolate()); 7882 right_type = handle(Type::Any(), isolate());
7911 } else { 7883 } else {
7912 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); 7884 if (!maybe_string_add) right = TruncateToNumber(right, &right_type);
7913 right_rep = Representation::FromType(right_type); 7885 right_rep = Representation::FromType(right_type);
7914 } 7886 }
7915 7887
7888 if (binop_stub) {
7889 left = EnforceNumberType(left, left_type);
7890 right = EnforceNumberType(right, right_type);
7891 }
7892
7916 Representation result_rep = Representation::FromType(result_type); 7893 Representation result_rep = Representation::FromType(result_type);
7917 7894
7918 bool is_string_add = op == Token::ADD && 7895 bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) ||
7919 (left_type->Is(Type::String()) || 7896 (right_rep.IsTagged() && !right_rep.IsSmi());
7920 right_type->Is(Type::String())); 7897 bool is_string_add = op == Token::ADD &&
7898 (left_type->Is(Type::String()) ||
7899 right_type->Is(Type::String()));
7921 7900
7922 HInstruction* instr = NULL; 7901 HInstruction* instr = NULL;
7923 switch (op) { 7902 // Only the stub is allowed to call into the runtime, since otherwise we would
7924 case Token::ADD: 7903 // inline several instructions (including the two pushes) for every tagged
7925 if (is_string_add) { 7904 // operation in optimized code, which is more expensive, than a stub call.
7926 StringAddFlags flags = STRING_ADD_CHECK_BOTH; 7905 if (binop_stub && is_non_primitive && !is_string_add) {
7927 if (left_type->Is(Type::String())) { 7906 HValue* function = AddLoadJSBuiltin(BinaryOpIC::TokenToJSBuiltin(op));
7928 BuildCheckHeapObject(left); 7907 Add<HPushArgument>(left);
7929 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); 7908 Add<HPushArgument>(right);
7930 flags = STRING_ADD_CHECK_RIGHT; 7909 instr = NewUncasted<HInvokeFunction>(function, 2);
7910 } else {
7911 switch (op) {
7912 case Token::ADD:
7913 if (is_string_add) {
7914 StringAddFlags flags = STRING_ADD_CHECK_BOTH;
7915 if (left_type->Is(Type::String())) {
7916 BuildCheckHeapObject(left);
7917 AddInstruction(HCheckInstanceType::NewIsString(left, zone()));
7918 flags = STRING_ADD_CHECK_RIGHT;
7919 }
7920 if (right_type->Is(Type::String())) {
7921 BuildCheckHeapObject(right);
7922 AddInstruction(HCheckInstanceType::NewIsString(right, zone()));
7923 flags = (flags == STRING_ADD_CHECK_BOTH)
7924 ? STRING_ADD_CHECK_LEFT : STRING_ADD_CHECK_NONE;
7925 }
7926 instr = NewUncasted<HStringAdd>(left, right, flags);
7927 } else {
7928 instr = NewUncasted<HAdd>(left, right);
7931 } 7929 }
7932 if (right_type->Is(Type::String())) { 7930 break;
7933 BuildCheckHeapObject(right); 7931 case Token::SUB:
7934 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); 7932 instr = NewUncasted<HSub>(left, right);
7935 flags = (flags == STRING_ADD_CHECK_BOTH) 7933 break;
7936 ? STRING_ADD_CHECK_LEFT : STRING_ADD_CHECK_NONE; 7934 case Token::MUL:
7935 instr = NewUncasted<HMul>(left, right);
7936 break;
7937 case Token::MOD:
7938 instr = NewUncasted<HMod>(left, right, fixed_right_arg);
7939 break;
7940 case Token::DIV:
7941 instr = NewUncasted<HDiv>(left, right);
7942 break;
7943 case Token::BIT_XOR:
7944 case Token::BIT_AND:
7945 instr = NewUncasted<HBitwise>(op, left, right);
7946 break;
7947 case Token::BIT_OR: {
7948 HValue* operand, *shift_amount;
7949 if (left_type->Is(Type::Signed32()) &&
7950 right_type->Is(Type::Signed32()) &&
7951 MatchRotateRight(left, right, &operand, &shift_amount)) {
7952 instr = NewUncasted<HRor>(operand, shift_amount);
7953 } else {
7954 instr = NewUncasted<HBitwise>(op, left, right);
7937 } 7955 }
7938 instr = NewUncasted<HStringAdd>(left, right, flags); 7956 break;
7939 } else {
7940 instr = NewUncasted<HAdd>(left, right);
7941 } 7957 }
7942 break; 7958 case Token::SAR:
7943 case Token::SUB: 7959 instr = NewUncasted<HSar>(left, right);
7944 instr = NewUncasted<HSub>(left, right); 7960 break;
7945 break; 7961 case Token::SHR:
7946 case Token::MUL: 7962 instr = NewUncasted<HShr>(left, right);
7947 instr = NewUncasted<HMul>(left, right); 7963 if (FLAG_opt_safe_uint32_operations && instr->IsShr() &&
7948 break; 7964 CanBeZero(right)) {
7949 case Token::MOD: 7965 graph()->RecordUint32Instruction(instr);
7950 instr = NewUncasted<HMod>(left, right, fixed_right_arg); 7966 }
7951 break; 7967 break;
7952 case Token::DIV: 7968 case Token::SHL:
7953 instr = NewUncasted<HDiv>(left, right); 7969 instr = NewUncasted<HShl>(left, right);
7954 break; 7970 break;
7955 case Token::BIT_XOR: 7971 default:
7956 case Token::BIT_AND: 7972 UNREACHABLE();
7957 instr = NewUncasted<HBitwise>(op, left, right);
7958 break;
7959 case Token::BIT_OR: {
7960 HValue* operand, *shift_amount;
7961 if (left_type->Is(Type::Signed32()) &&
7962 right_type->Is(Type::Signed32()) &&
7963 MatchRotateRight(left, right, &operand, &shift_amount)) {
7964 instr = NewUncasted<HRor>(operand, shift_amount);
7965 } else {
7966 instr = NewUncasted<HBitwise>(op, left, right);
7967 }
7968 break;
7969 } 7973 }
7970 case Token::SAR:
7971 instr = NewUncasted<HSar>(left, right);
7972 break;
7973 case Token::SHR:
7974 instr = NewUncasted<HShr>(left, right);
7975 if (FLAG_opt_safe_uint32_operations && instr->IsShr() &&
7976 CanBeZero(right)) {
7977 graph()->RecordUint32Instruction(instr);
7978 }
7979 break;
7980 case Token::SHL:
7981 instr = NewUncasted<HShl>(left, right);
7982 break;
7983 default:
7984 UNREACHABLE();
7985 } 7974 }
7986 7975
7987 if (instr->IsBinaryOperation()) { 7976 if (instr->IsBinaryOperation()) {
7988 HBinaryOperation* binop = HBinaryOperation::cast(instr); 7977 HBinaryOperation* binop = HBinaryOperation::cast(instr);
7989 binop->set_observed_input_representation(1, left_rep); 7978 binop->set_observed_input_representation(1, left_rep);
7990 binop->set_observed_input_representation(2, right_rep); 7979 binop->set_observed_input_representation(2, right_rep);
7991 binop->initialize_output_representation(result_rep); 7980 binop->initialize_output_representation(result_rep);
7981 if (binop_stub) {
7982 // Stub should not call into stub.
7983 instr->SetFlag(HValue::kCannotBeTagged);
7984 // And should truncate on HForceRepresentation already.
7985 if (left->IsForceRepresentation()) {
7986 left->CopyFlag(HValue::kTruncatingToSmi, instr);
7987 left->CopyFlag(HValue::kTruncatingToInt32, instr);
7988 }
7989 if (right->IsForceRepresentation()) {
7990 right->CopyFlag(HValue::kTruncatingToSmi, instr);
7991 right->CopyFlag(HValue::kTruncatingToInt32, instr);
7992 }
7993 }
7992 } 7994 }
7993 return instr; 7995 return instr;
7994 } 7996 }
7995 7997
7996 7998
7997 // Check for the form (%_ClassOf(foo) === 'BarClass'). 7999 // Check for the form (%_ClassOf(foo) === 'BarClass').
7998 static bool IsClassOfTest(CompareOperation* expr) { 8000 static bool IsClassOfTest(CompareOperation* expr) {
7999 if (expr->op() != Token::EQ_STRICT) return false; 8001 if (expr->op() != Token::EQ_STRICT) return false;
8000 CallRuntime* call = expr->left()->AsCallRuntime(); 8002 CallRuntime* call = expr->left()->AsCallRuntime();
8001 if (call == NULL) return false; 8003 if (call == NULL) return false;
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after
8313 } else if (combined_type->Is(Type::InternalizedString()) && 8315 } else if (combined_type->Is(Type::InternalizedString()) &&
8314 Token::IsEqualityOp(op)) { 8316 Token::IsEqualityOp(op)) {
8315 BuildCheckHeapObject(left); 8317 BuildCheckHeapObject(left);
8316 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone())); 8318 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone()));
8317 BuildCheckHeapObject(right); 8319 BuildCheckHeapObject(right);
8318 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone())); 8320 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone()));
8319 HCompareObjectEqAndBranch* result = 8321 HCompareObjectEqAndBranch* result =
8320 New<HCompareObjectEqAndBranch>(left, right); 8322 New<HCompareObjectEqAndBranch>(left, right);
8321 result->set_position(expr->position()); 8323 result->set_position(expr->position());
8322 return ast_context()->ReturnControl(result, expr->id()); 8324 return ast_context()->ReturnControl(result, expr->id());
8325 } else if (combined_type->Is(Type::String())) {
8326 BuildCheckHeapObject(left);
8327 AddInstruction(HCheckInstanceType::NewIsString(left, zone()));
8328 BuildCheckHeapObject(right);
8329 AddInstruction(HCheckInstanceType::NewIsString(right, zone()));
8330 HStringCompareAndBranch* result =
8331 New<HStringCompareAndBranch>(left, right, op);
8332 result->set_position(expr->position());
8333 return ast_context()->ReturnControl(result, expr->id());
8334 } else if (combined_type->NumClasses() == 1 && Token::IsEqualityOp(op)) {
8335 BuildCheckHeapObject(left);
8336 BuildCheckMap(left, combined_type->Classes().Current());
8337 BuildCheckHeapObject(right);
8338 BuildCheckMap(right, combined_type->Classes().Current());
8339 HCompareObjectEqAndBranch* result =
8340 New<HCompareObjectEqAndBranch>(left, right);
8341 result->set_position(expr->position());
8342 return ast_context()->ReturnInstruction(result, expr->id());
8343 } else if (combined_type->Is(Type::Receiver()) && Token::IsEqualityOp(op)) {
8344 BuildCheckHeapObject(left);
8345 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone()));
8346 BuildCheckHeapObject(right);
8347 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone()));
8348 HCompareObjectEqAndBranch* result =
8349 New<HCompareObjectEqAndBranch>(left, right);
8350 result->set_position(expr->position());
8351 return ast_context()->ReturnInstruction(result, expr->id());
8323 } else { 8352 } else {
8324 if (combined_rep.IsTagged() || combined_rep.IsNone()) { 8353 if (combined_rep.IsTagged() || combined_rep.IsNone()) {
8325 HCompareGeneric* result = 8354 HCompareGeneric* result =
8326 new(zone()) HCompareGeneric(context, left, right, op); 8355 new(zone()) HCompareGeneric(context, left, right, op);
8327 result->set_observed_input_representation(1, left_rep); 8356 result->set_observed_input_representation(1, left_rep);
8328 result->set_observed_input_representation(2, right_rep); 8357 result->set_observed_input_representation(2, right_rep);
8329 result->set_position(expr->position()); 8358 result->set_position(expr->position());
8330 return ast_context()->ReturnInstruction(result, expr->id()); 8359 return ast_context()->ReturnInstruction(result, expr->id());
8331 } else { 8360 } else {
8332 HCompareNumericAndBranch* result = 8361 HCompareNumericAndBranch* result =
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
8374 if (function_state()->outer() != NULL) { 8403 if (function_state()->outer() != NULL) {
8375 return New<HConstant>( 8404 return New<HConstant>(
8376 function_state()->compilation_info()->closure()); 8405 function_state()->compilation_info()->closure());
8377 } else { 8406 } else {
8378 return new(zone()) HThisFunction; 8407 return new(zone()) HThisFunction;
8379 } 8408 }
8380 } 8409 }
8381 8410
8382 8411
8383 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( 8412 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
8384 Handle<JSObject> boilerplate_object, 8413 Handle<JSObject> boilerplate_object) {
8385 Handle<Object> allocation_site_object,
8386 AllocationSiteMode mode) {
8387 NoObservableSideEffectsScope no_effects(this); 8414 NoObservableSideEffectsScope no_effects(this);
8415 InstanceType instance_type = boilerplate_object->map()->instance_type();
8416 ASSERT(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE);
8388 8417
8389 Handle<FixedArrayBase> elements(boilerplate_object->elements());
8390 int object_size = boilerplate_object->map()->instance_size();
8391 int object_offset = object_size;
8392
8393 InstanceType instance_type = boilerplate_object->map()->instance_type();
8394 bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE;
8395
8396 // If using allocation sites, then
8397 // 1) the payload on the site should already be filled in as a valid
8398 // (boilerplate) array, and
8399 // 2) we shouldn't be pretenuring the allocations.
8400 ASSERT(!create_allocation_site_info ||
8401 (AllocationSite::cast(*allocation_site_object)->IsLiteralSite() &&
8402 isolate()->heap()->GetPretenureMode() == NOT_TENURED));
8403
8404 if (create_allocation_site_info) {
8405 object_size += AllocationMemento::kSize;
8406 }
8407
8408 ASSERT(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE);
8409 HType type = instance_type == JS_ARRAY_TYPE 8418 HType type = instance_type == JS_ARRAY_TYPE
8410 ? HType::JSArray() : HType::JSObject(); 8419 ? HType::JSArray() : HType::JSObject();
8411 HValue* object_size_constant = Add<HConstant>(object_size); 8420 HValue* object_size_constant = Add<HConstant>(
8421 boilerplate_object->map()->instance_size());
8412 HInstruction* object = Add<HAllocate>(object_size_constant, type, 8422 HInstruction* object = Add<HAllocate>(object_size_constant, type,
8413 isolate()->heap()->GetPretenureMode(), instance_type); 8423 isolate()->heap()->GetPretenureMode(), instance_type);
8414 8424
8415 BuildEmitObjectHeader(boilerplate_object, object); 8425 BuildEmitObjectHeader(boilerplate_object, object);
8416 8426
8417 if (create_allocation_site_info) { 8427 Handle<FixedArrayBase> elements(boilerplate_object->elements());
8418 HInstruction* allocation_site = Add<HConstant>(allocation_site_object);
8419 BuildCreateAllocationMemento(object, object_offset, allocation_site);
8420 }
8421
8422 int elements_size = (elements->length() > 0 && 8428 int elements_size = (elements->length() > 0 &&
8423 elements->map() != isolate()->heap()->fixed_cow_array_map()) ? 8429 elements->map() != isolate()->heap()->fixed_cow_array_map()) ?
8424 elements->Size() : 0; 8430 elements->Size() : 0;
8425 8431
8426 HInstruction* object_elements = NULL; 8432 HInstruction* object_elements = NULL;
8427 if (elements_size > 0) { 8433 if (elements_size > 0) {
8428 HValue* object_elements_size = Add<HConstant>(elements_size); 8434 HValue* object_elements_size = Add<HConstant>(elements_size);
8429 if (boilerplate_object->HasFastDoubleElements()) { 8435 if (boilerplate_object->HasFastDoubleElements()) {
8430 object_elements = Add<HAllocate>(object_elements_size, HType::JSObject(), 8436 object_elements = Add<HAllocate>(object_elements_size, HType::JSObject(),
8431 isolate()->heap()->GetPretenureMode(), FIXED_DOUBLE_ARRAY_TYPE); 8437 isolate()->heap()->GetPretenureMode(), FIXED_DOUBLE_ARRAY_TYPE);
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
8513 Handle<Object>(boilerplate_object->InObjectPropertyAt(index), 8519 Handle<Object>(boilerplate_object->InObjectPropertyAt(index),
8514 isolate()); 8520 isolate());
8515 8521
8516 // The access for the store depends on the type of the boilerplate. 8522 // The access for the store depends on the type of the boilerplate.
8517 HObjectAccess access = boilerplate_object->IsJSArray() ? 8523 HObjectAccess access = boilerplate_object->IsJSArray() ?
8518 HObjectAccess::ForJSArrayOffset(property_offset) : 8524 HObjectAccess::ForJSArrayOffset(property_offset) :
8519 HObjectAccess::ForJSObjectOffset(property_offset); 8525 HObjectAccess::ForJSObjectOffset(property_offset);
8520 8526
8521 if (value->IsJSObject()) { 8527 if (value->IsJSObject()) {
8522 Handle<JSObject> value_object = Handle<JSObject>::cast(value); 8528 Handle<JSObject> value_object = Handle<JSObject>::cast(value);
8523 HInstruction* result = 8529 HInstruction* result = BuildFastLiteral(value_object);
8524 BuildFastLiteral(value_object,
8525 Handle<Object>::null(), DONT_TRACK_ALLOCATION_SITE);
8526 Add<HStoreNamedField>(object, access, result); 8530 Add<HStoreNamedField>(object, access, result);
8527 } else { 8531 } else {
8528 Representation representation = details.representation(); 8532 Representation representation = details.representation();
8529 HInstruction* value_instruction = Add<HConstant>(value); 8533 HInstruction* value_instruction = Add<HConstant>(value);
8530 8534
8531 if (representation.IsDouble()) { 8535 if (representation.IsDouble()) {
8532 // Allocate a HeapNumber box and store the value into it. 8536 // Allocate a HeapNumber box and store the value into it.
8533 HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize); 8537 HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize);
8534 HInstruction* double_box = 8538 HInstruction* double_box =
8535 Add<HAllocate>(heap_number_constant, HType::HeapNumber(), 8539 Add<HAllocate>(heap_number_constant, HType::HeapNumber(),
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
8601 ElementsKind kind, 8605 ElementsKind kind,
8602 HValue* object_elements) { 8606 HValue* object_elements) {
8603 HInstruction* boilerplate_elements = Add<HConstant>(elements); 8607 HInstruction* boilerplate_elements = Add<HConstant>(elements);
8604 int elements_length = elements->length(); 8608 int elements_length = elements->length();
8605 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); 8609 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
8606 for (int i = 0; i < elements_length; i++) { 8610 for (int i = 0; i < elements_length; i++) {
8607 Handle<Object> value(fast_elements->get(i), isolate()); 8611 Handle<Object> value(fast_elements->get(i), isolate());
8608 HValue* key_constant = Add<HConstant>(i); 8612 HValue* key_constant = Add<HConstant>(i);
8609 if (value->IsJSObject()) { 8613 if (value->IsJSObject()) {
8610 Handle<JSObject> value_object = Handle<JSObject>::cast(value); 8614 Handle<JSObject> value_object = Handle<JSObject>::cast(value);
8611 HInstruction* result = 8615 HInstruction* result = BuildFastLiteral(value_object);
8612 BuildFastLiteral(value_object,
8613 Handle<Object>::null(), DONT_TRACK_ALLOCATION_SITE);
8614 Add<HStoreKeyed>(object_elements, key_constant, result, kind); 8616 Add<HStoreKeyed>(object_elements, key_constant, result, kind);
8615 } else { 8617 } else {
8616 HInstruction* value_instruction = 8618 HInstruction* value_instruction =
8617 Add<HLoadKeyed>(boilerplate_elements, key_constant, 8619 Add<HLoadKeyed>(boilerplate_elements, key_constant,
8618 static_cast<HValue*>(NULL), kind, 8620 static_cast<HValue*>(NULL), kind,
8619 ALLOW_RETURN_HOLE); 8621 ALLOW_RETURN_HOLE);
8620 Add<HStoreKeyed>(object_elements, key_constant, value_instruction, kind); 8622 Add<HStoreKeyed>(object_elements, key_constant, value_instruction, kind);
8621 } 8623 }
8622 } 8624 }
8623 } 8625 }
(...skipping 1251 matching lines...) Expand 10 before | Expand all | Expand 10 after
9875 if (ShouldProduceTraceOutput()) { 9877 if (ShouldProduceTraceOutput()) {
9876 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 9878 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
9877 } 9879 }
9878 9880
9879 #ifdef DEBUG 9881 #ifdef DEBUG
9880 graph_->Verify(false); // No full verify. 9882 graph_->Verify(false); // No full verify.
9881 #endif 9883 #endif
9882 } 9884 }
9883 9885
9884 } } // namespace v8::internal 9886 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-deoptimizing-mark.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698