OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/hydrogen.h" | 5 #include "src/hydrogen.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "src/v8.h" | 9 #include "src/v8.h" |
10 | 10 |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 return graph_->isolate(); | 92 return graph_->isolate(); |
93 } | 93 } |
94 | 94 |
95 | 95 |
96 void HBasicBlock::MarkUnreachable() { | 96 void HBasicBlock::MarkUnreachable() { |
97 is_reachable_ = false; | 97 is_reachable_ = false; |
98 } | 98 } |
99 | 99 |
100 | 100 |
101 void HBasicBlock::AttachLoopInformation() { | 101 void HBasicBlock::AttachLoopInformation() { |
102 ASSERT(!IsLoopHeader()); | 102 DCHECK(!IsLoopHeader()); |
103 loop_information_ = new(zone()) HLoopInformation(this, zone()); | 103 loop_information_ = new(zone()) HLoopInformation(this, zone()); |
104 } | 104 } |
105 | 105 |
106 | 106 |
107 void HBasicBlock::DetachLoopInformation() { | 107 void HBasicBlock::DetachLoopInformation() { |
108 ASSERT(IsLoopHeader()); | 108 DCHECK(IsLoopHeader()); |
109 loop_information_ = NULL; | 109 loop_information_ = NULL; |
110 } | 110 } |
111 | 111 |
112 | 112 |
113 void HBasicBlock::AddPhi(HPhi* phi) { | 113 void HBasicBlock::AddPhi(HPhi* phi) { |
114 ASSERT(!IsStartBlock()); | 114 DCHECK(!IsStartBlock()); |
115 phis_.Add(phi, zone()); | 115 phis_.Add(phi, zone()); |
116 phi->SetBlock(this); | 116 phi->SetBlock(this); |
117 } | 117 } |
118 | 118 |
119 | 119 |
120 void HBasicBlock::RemovePhi(HPhi* phi) { | 120 void HBasicBlock::RemovePhi(HPhi* phi) { |
121 ASSERT(phi->block() == this); | 121 DCHECK(phi->block() == this); |
122 ASSERT(phis_.Contains(phi)); | 122 DCHECK(phis_.Contains(phi)); |
123 phi->Kill(); | 123 phi->Kill(); |
124 phis_.RemoveElement(phi); | 124 phis_.RemoveElement(phi); |
125 phi->SetBlock(NULL); | 125 phi->SetBlock(NULL); |
126 } | 126 } |
127 | 127 |
128 | 128 |
129 void HBasicBlock::AddInstruction(HInstruction* instr, | 129 void HBasicBlock::AddInstruction(HInstruction* instr, |
130 HSourcePosition position) { | 130 HSourcePosition position) { |
131 ASSERT(!IsStartBlock() || !IsFinished()); | 131 DCHECK(!IsStartBlock() || !IsFinished()); |
132 ASSERT(!instr->IsLinked()); | 132 DCHECK(!instr->IsLinked()); |
133 ASSERT(!IsFinished()); | 133 DCHECK(!IsFinished()); |
134 | 134 |
135 if (!position.IsUnknown()) { | 135 if (!position.IsUnknown()) { |
136 instr->set_position(position); | 136 instr->set_position(position); |
137 } | 137 } |
138 if (first_ == NULL) { | 138 if (first_ == NULL) { |
139 ASSERT(last_environment() != NULL); | 139 DCHECK(last_environment() != NULL); |
140 ASSERT(!last_environment()->ast_id().IsNone()); | 140 DCHECK(!last_environment()->ast_id().IsNone()); |
141 HBlockEntry* entry = new(zone()) HBlockEntry(); | 141 HBlockEntry* entry = new(zone()) HBlockEntry(); |
142 entry->InitializeAsFirst(this); | 142 entry->InitializeAsFirst(this); |
143 if (!position.IsUnknown()) { | 143 if (!position.IsUnknown()) { |
144 entry->set_position(position); | 144 entry->set_position(position); |
145 } else { | 145 } else { |
146 ASSERT(!FLAG_hydrogen_track_positions || | 146 DCHECK(!FLAG_hydrogen_track_positions || |
147 !graph()->info()->IsOptimizing()); | 147 !graph()->info()->IsOptimizing()); |
148 } | 148 } |
149 first_ = last_ = entry; | 149 first_ = last_ = entry; |
150 } | 150 } |
151 instr->InsertAfter(last_); | 151 instr->InsertAfter(last_); |
152 } | 152 } |
153 | 153 |
154 | 154 |
155 HPhi* HBasicBlock::AddNewPhi(int merged_index) { | 155 HPhi* HBasicBlock::AddNewPhi(int merged_index) { |
156 if (graph()->IsInsideNoSideEffectsScope()) { | 156 if (graph()->IsInsideNoSideEffectsScope()) { |
157 merged_index = HPhi::kInvalidMergedIndex; | 157 merged_index = HPhi::kInvalidMergedIndex; |
158 } | 158 } |
159 HPhi* phi = new(zone()) HPhi(merged_index, zone()); | 159 HPhi* phi = new(zone()) HPhi(merged_index, zone()); |
160 AddPhi(phi); | 160 AddPhi(phi); |
161 return phi; | 161 return phi; |
162 } | 162 } |
163 | 163 |
164 | 164 |
165 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id, | 165 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id, |
166 RemovableSimulate removable) { | 166 RemovableSimulate removable) { |
167 ASSERT(HasEnvironment()); | 167 DCHECK(HasEnvironment()); |
168 HEnvironment* environment = last_environment(); | 168 HEnvironment* environment = last_environment(); |
169 ASSERT(ast_id.IsNone() || | 169 DCHECK(ast_id.IsNone() || |
170 ast_id == BailoutId::StubEntry() || | 170 ast_id == BailoutId::StubEntry() || |
171 environment->closure()->shared()->VerifyBailoutId(ast_id)); | 171 environment->closure()->shared()->VerifyBailoutId(ast_id)); |
172 | 172 |
173 int push_count = environment->push_count(); | 173 int push_count = environment->push_count(); |
174 int pop_count = environment->pop_count(); | 174 int pop_count = environment->pop_count(); |
175 | 175 |
176 HSimulate* instr = | 176 HSimulate* instr = |
177 new(zone()) HSimulate(ast_id, pop_count, zone(), removable); | 177 new(zone()) HSimulate(ast_id, pop_count, zone(), removable); |
178 #ifdef DEBUG | 178 #ifdef DEBUG |
179 instr->set_closure(environment->closure()); | 179 instr->set_closure(environment->closure()); |
(...skipping 10 matching lines...) Expand all Loading... |
190 it.Advance()) { | 190 it.Advance()) { |
191 int index = it.Current(); | 191 int index = it.Current(); |
192 instr->AddAssignedValue(index, environment->Lookup(index)); | 192 instr->AddAssignedValue(index, environment->Lookup(index)); |
193 } | 193 } |
194 environment->ClearHistory(); | 194 environment->ClearHistory(); |
195 return instr; | 195 return instr; |
196 } | 196 } |
197 | 197 |
198 | 198 |
199 void HBasicBlock::Finish(HControlInstruction* end, HSourcePosition position) { | 199 void HBasicBlock::Finish(HControlInstruction* end, HSourcePosition position) { |
200 ASSERT(!IsFinished()); | 200 DCHECK(!IsFinished()); |
201 AddInstruction(end, position); | 201 AddInstruction(end, position); |
202 end_ = end; | 202 end_ = end; |
203 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { | 203 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { |
204 it.Current()->RegisterPredecessor(this); | 204 it.Current()->RegisterPredecessor(this); |
205 } | 205 } |
206 } | 206 } |
207 | 207 |
208 | 208 |
209 void HBasicBlock::Goto(HBasicBlock* block, | 209 void HBasicBlock::Goto(HBasicBlock* block, |
210 HSourcePosition position, | 210 HSourcePosition position, |
(...skipping 16 matching lines...) Expand all Loading... |
227 Finish(instr, position); | 227 Finish(instr, position); |
228 } | 228 } |
229 | 229 |
230 | 230 |
231 void HBasicBlock::AddLeaveInlined(HValue* return_value, | 231 void HBasicBlock::AddLeaveInlined(HValue* return_value, |
232 FunctionState* state, | 232 FunctionState* state, |
233 HSourcePosition position) { | 233 HSourcePosition position) { |
234 HBasicBlock* target = state->function_return(); | 234 HBasicBlock* target = state->function_return(); |
235 bool drop_extra = state->inlining_kind() == NORMAL_RETURN; | 235 bool drop_extra = state->inlining_kind() == NORMAL_RETURN; |
236 | 236 |
237 ASSERT(target->IsInlineReturnTarget()); | 237 DCHECK(target->IsInlineReturnTarget()); |
238 ASSERT(return_value != NULL); | 238 DCHECK(return_value != NULL); |
239 HEnvironment* env = last_environment(); | 239 HEnvironment* env = last_environment(); |
240 int argument_count = env->arguments_environment()->parameter_count(); | 240 int argument_count = env->arguments_environment()->parameter_count(); |
241 AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count), | 241 AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count), |
242 position); | 242 position); |
243 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); | 243 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); |
244 last_environment()->Push(return_value); | 244 last_environment()->Push(return_value); |
245 AddNewSimulate(BailoutId::None(), position); | 245 AddNewSimulate(BailoutId::None(), position); |
246 HGoto* instr = new(zone()) HGoto(target); | 246 HGoto* instr = new(zone()) HGoto(target); |
247 Finish(instr, position); | 247 Finish(instr, position); |
248 } | 248 } |
249 | 249 |
250 | 250 |
251 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) { | 251 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) { |
252 ASSERT(!HasEnvironment()); | 252 DCHECK(!HasEnvironment()); |
253 ASSERT(first() == NULL); | 253 DCHECK(first() == NULL); |
254 UpdateEnvironment(env); | 254 UpdateEnvironment(env); |
255 } | 255 } |
256 | 256 |
257 | 257 |
258 void HBasicBlock::UpdateEnvironment(HEnvironment* env) { | 258 void HBasicBlock::UpdateEnvironment(HEnvironment* env) { |
259 last_environment_ = env; | 259 last_environment_ = env; |
260 graph()->update_maximum_environment_size(env->first_expression_index()); | 260 graph()->update_maximum_environment_size(env->first_expression_index()); |
261 } | 261 } |
262 | 262 |
263 | 263 |
264 void HBasicBlock::SetJoinId(BailoutId ast_id) { | 264 void HBasicBlock::SetJoinId(BailoutId ast_id) { |
265 int length = predecessors_.length(); | 265 int length = predecessors_.length(); |
266 ASSERT(length > 0); | 266 DCHECK(length > 0); |
267 for (int i = 0; i < length; i++) { | 267 for (int i = 0; i < length; i++) { |
268 HBasicBlock* predecessor = predecessors_[i]; | 268 HBasicBlock* predecessor = predecessors_[i]; |
269 ASSERT(predecessor->end()->IsGoto()); | 269 DCHECK(predecessor->end()->IsGoto()); |
270 HSimulate* simulate = HSimulate::cast(predecessor->end()->previous()); | 270 HSimulate* simulate = HSimulate::cast(predecessor->end()->previous()); |
271 ASSERT(i != 0 || | 271 DCHECK(i != 0 || |
272 (predecessor->last_environment()->closure().is_null() || | 272 (predecessor->last_environment()->closure().is_null() || |
273 predecessor->last_environment()->closure()->shared() | 273 predecessor->last_environment()->closure()->shared() |
274 ->VerifyBailoutId(ast_id))); | 274 ->VerifyBailoutId(ast_id))); |
275 simulate->set_ast_id(ast_id); | 275 simulate->set_ast_id(ast_id); |
276 predecessor->last_environment()->set_ast_id(ast_id); | 276 predecessor->last_environment()->set_ast_id(ast_id); |
277 } | 277 } |
278 } | 278 } |
279 | 279 |
280 | 280 |
281 bool HBasicBlock::Dominates(HBasicBlock* other) const { | 281 bool HBasicBlock::Dominates(HBasicBlock* other) const { |
(...skipping 17 matching lines...) Expand all Loading... |
299 int result = (current->IsLoopHeader()) ? 1 : 0; | 299 int result = (current->IsLoopHeader()) ? 1 : 0; |
300 while (current->parent_loop_header() != NULL) { | 300 while (current->parent_loop_header() != NULL) { |
301 current = current->parent_loop_header(); | 301 current = current->parent_loop_header(); |
302 result++; | 302 result++; |
303 } | 303 } |
304 return result; | 304 return result; |
305 } | 305 } |
306 | 306 |
307 | 307 |
308 void HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) { | 308 void HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) { |
309 ASSERT(IsLoopHeader()); | 309 DCHECK(IsLoopHeader()); |
310 | 310 |
311 SetJoinId(stmt->EntryId()); | 311 SetJoinId(stmt->EntryId()); |
312 if (predecessors()->length() == 1) { | 312 if (predecessors()->length() == 1) { |
313 // This is a degenerated loop. | 313 // This is a degenerated loop. |
314 DetachLoopInformation(); | 314 DetachLoopInformation(); |
315 return; | 315 return; |
316 } | 316 } |
317 | 317 |
318 // Only the first entry into the loop is from outside the loop. All other | 318 // Only the first entry into the loop is from outside the loop. All other |
319 // entries must be back edges. | 319 // entries must be back edges. |
320 for (int i = 1; i < predecessors()->length(); ++i) { | 320 for (int i = 1; i < predecessors()->length(); ++i) { |
321 loop_information()->RegisterBackEdge(predecessors()->at(i)); | 321 loop_information()->RegisterBackEdge(predecessors()->at(i)); |
322 } | 322 } |
323 } | 323 } |
324 | 324 |
325 | 325 |
326 void HBasicBlock::MarkSuccEdgeUnreachable(int succ) { | 326 void HBasicBlock::MarkSuccEdgeUnreachable(int succ) { |
327 ASSERT(IsFinished()); | 327 DCHECK(IsFinished()); |
328 HBasicBlock* succ_block = end()->SuccessorAt(succ); | 328 HBasicBlock* succ_block = end()->SuccessorAt(succ); |
329 | 329 |
330 ASSERT(succ_block->predecessors()->length() == 1); | 330 DCHECK(succ_block->predecessors()->length() == 1); |
331 succ_block->MarkUnreachable(); | 331 succ_block->MarkUnreachable(); |
332 } | 332 } |
333 | 333 |
334 | 334 |
335 void HBasicBlock::RegisterPredecessor(HBasicBlock* pred) { | 335 void HBasicBlock::RegisterPredecessor(HBasicBlock* pred) { |
336 if (HasPredecessor()) { | 336 if (HasPredecessor()) { |
337 // Only loop header blocks can have a predecessor added after | 337 // Only loop header blocks can have a predecessor added after |
338 // instructions have been added to the block (they have phis for all | 338 // instructions have been added to the block (they have phis for all |
339 // values in the environment, these phis may be eliminated later). | 339 // values in the environment, these phis may be eliminated later). |
340 ASSERT(IsLoopHeader() || first_ == NULL); | 340 DCHECK(IsLoopHeader() || first_ == NULL); |
341 HEnvironment* incoming_env = pred->last_environment(); | 341 HEnvironment* incoming_env = pred->last_environment(); |
342 if (IsLoopHeader()) { | 342 if (IsLoopHeader()) { |
343 ASSERT(phis()->length() == incoming_env->length()); | 343 DCHECK(phis()->length() == incoming_env->length()); |
344 for (int i = 0; i < phis_.length(); ++i) { | 344 for (int i = 0; i < phis_.length(); ++i) { |
345 phis_[i]->AddInput(incoming_env->values()->at(i)); | 345 phis_[i]->AddInput(incoming_env->values()->at(i)); |
346 } | 346 } |
347 } else { | 347 } else { |
348 last_environment()->AddIncomingEdge(this, pred->last_environment()); | 348 last_environment()->AddIncomingEdge(this, pred->last_environment()); |
349 } | 349 } |
350 } else if (!HasEnvironment() && !IsFinished()) { | 350 } else if (!HasEnvironment() && !IsFinished()) { |
351 ASSERT(!IsLoopHeader()); | 351 DCHECK(!IsLoopHeader()); |
352 SetInitialEnvironment(pred->last_environment()->Copy()); | 352 SetInitialEnvironment(pred->last_environment()->Copy()); |
353 } | 353 } |
354 | 354 |
355 predecessors_.Add(pred, zone()); | 355 predecessors_.Add(pred, zone()); |
356 } | 356 } |
357 | 357 |
358 | 358 |
359 void HBasicBlock::AddDominatedBlock(HBasicBlock* block) { | 359 void HBasicBlock::AddDominatedBlock(HBasicBlock* block) { |
360 ASSERT(!dominated_blocks_.Contains(block)); | 360 DCHECK(!dominated_blocks_.Contains(block)); |
361 // Keep the list of dominated blocks sorted such that if there is two | 361 // Keep the list of dominated blocks sorted such that if there is two |
362 // succeeding block in this list, the predecessor is before the successor. | 362 // succeeding block in this list, the predecessor is before the successor. |
363 int index = 0; | 363 int index = 0; |
364 while (index < dominated_blocks_.length() && | 364 while (index < dominated_blocks_.length() && |
365 dominated_blocks_[index]->block_id() < block->block_id()) { | 365 dominated_blocks_[index]->block_id() < block->block_id()) { |
366 ++index; | 366 ++index; |
367 } | 367 } |
368 dominated_blocks_.InsertAt(index, block, zone()); | 368 dominated_blocks_.InsertAt(index, block, zone()); |
369 } | 369 } |
370 | 370 |
371 | 371 |
372 void HBasicBlock::AssignCommonDominator(HBasicBlock* other) { | 372 void HBasicBlock::AssignCommonDominator(HBasicBlock* other) { |
373 if (dominator_ == NULL) { | 373 if (dominator_ == NULL) { |
374 dominator_ = other; | 374 dominator_ = other; |
375 other->AddDominatedBlock(this); | 375 other->AddDominatedBlock(this); |
376 } else if (other->dominator() != NULL) { | 376 } else if (other->dominator() != NULL) { |
377 HBasicBlock* first = dominator_; | 377 HBasicBlock* first = dominator_; |
378 HBasicBlock* second = other; | 378 HBasicBlock* second = other; |
379 | 379 |
380 while (first != second) { | 380 while (first != second) { |
381 if (first->block_id() > second->block_id()) { | 381 if (first->block_id() > second->block_id()) { |
382 first = first->dominator(); | 382 first = first->dominator(); |
383 } else { | 383 } else { |
384 second = second->dominator(); | 384 second = second->dominator(); |
385 } | 385 } |
386 ASSERT(first != NULL && second != NULL); | 386 DCHECK(first != NULL && second != NULL); |
387 } | 387 } |
388 | 388 |
389 if (dominator_ != first) { | 389 if (dominator_ != first) { |
390 ASSERT(dominator_->dominated_blocks_.Contains(this)); | 390 DCHECK(dominator_->dominated_blocks_.Contains(this)); |
391 dominator_->dominated_blocks_.RemoveElement(this); | 391 dominator_->dominated_blocks_.RemoveElement(this); |
392 dominator_ = first; | 392 dominator_ = first; |
393 first->AddDominatedBlock(this); | 393 first->AddDominatedBlock(this); |
394 } | 394 } |
395 } | 395 } |
396 } | 396 } |
397 | 397 |
398 | 398 |
399 void HBasicBlock::AssignLoopSuccessorDominators() { | 399 void HBasicBlock::AssignLoopSuccessorDominators() { |
400 // Mark blocks that dominate all subsequent reachable blocks inside their | 400 // Mark blocks that dominate all subsequent reachable blocks inside their |
(...skipping 21 matching lines...) Expand all Loading... |
422 } | 422 } |
423 | 423 |
424 // If more successors than predecessors have been seen in the loop up to | 424 // If more successors than predecessors have been seen in the loop up to |
425 // now, it's not possible to guarantee that the current block dominates | 425 // now, it's not possible to guarantee that the current block dominates |
426 // all of the blocks with higher IDs. In this case, assume conservatively | 426 // all of the blocks with higher IDs. In this case, assume conservatively |
427 // that those paths through loop that don't go through the current block | 427 // that those paths through loop that don't go through the current block |
428 // contain all of the loop's dependencies. Also be careful to record | 428 // contain all of the loop's dependencies. Also be careful to record |
429 // dominator information about the current loop that's being processed, | 429 // dominator information about the current loop that's being processed, |
430 // and not nested loops, which will be processed when | 430 // and not nested loops, which will be processed when |
431 // AssignLoopSuccessorDominators gets called on their header. | 431 // AssignLoopSuccessorDominators gets called on their header. |
432 ASSERT(outstanding_successors >= 0); | 432 DCHECK(outstanding_successors >= 0); |
433 HBasicBlock* parent_loop_header = dominator_candidate->parent_loop_header(); | 433 HBasicBlock* parent_loop_header = dominator_candidate->parent_loop_header(); |
434 if (outstanding_successors == 0 && | 434 if (outstanding_successors == 0 && |
435 (parent_loop_header == this && !dominator_candidate->IsLoopHeader())) { | 435 (parent_loop_header == this && !dominator_candidate->IsLoopHeader())) { |
436 dominator_candidate->MarkAsLoopSuccessorDominator(); | 436 dominator_candidate->MarkAsLoopSuccessorDominator(); |
437 } | 437 } |
438 HControlInstruction* end = dominator_candidate->end(); | 438 HControlInstruction* end = dominator_candidate->end(); |
439 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { | 439 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { |
440 HBasicBlock* successor = it.Current(); | 440 HBasicBlock* successor = it.Current(); |
441 // Only count successors that remain inside the loop and don't loop back | 441 // Only count successors that remain inside the loop and don't loop back |
442 // to a loop header. | 442 // to a loop header. |
443 if (successor->block_id() > dominator_candidate->block_id() && | 443 if (successor->block_id() > dominator_candidate->block_id() && |
444 successor->block_id() <= last->block_id()) { | 444 successor->block_id() <= last->block_id()) { |
445 // Backwards edges must land on loop headers. | 445 // Backwards edges must land on loop headers. |
446 ASSERT(successor->block_id() > dominator_candidate->block_id() || | 446 DCHECK(successor->block_id() > dominator_candidate->block_id() || |
447 successor->IsLoopHeader()); | 447 successor->IsLoopHeader()); |
448 outstanding_successors++; | 448 outstanding_successors++; |
449 } | 449 } |
450 } | 450 } |
451 } | 451 } |
452 } | 452 } |
453 | 453 |
454 | 454 |
455 int HBasicBlock::PredecessorIndexOf(HBasicBlock* predecessor) const { | 455 int HBasicBlock::PredecessorIndexOf(HBasicBlock* predecessor) const { |
456 for (int i = 0; i < predecessors_.length(); ++i) { | 456 for (int i = 0; i < predecessors_.length(); ++i) { |
457 if (predecessors_[i] == predecessor) return i; | 457 if (predecessors_[i] == predecessor) return i; |
458 } | 458 } |
459 UNREACHABLE(); | 459 UNREACHABLE(); |
460 return -1; | 460 return -1; |
461 } | 461 } |
462 | 462 |
463 | 463 |
464 #ifdef DEBUG | 464 #ifdef DEBUG |
465 void HBasicBlock::Verify() { | 465 void HBasicBlock::Verify() { |
466 // Check that every block is finished. | 466 // Check that every block is finished. |
467 ASSERT(IsFinished()); | 467 DCHECK(IsFinished()); |
468 ASSERT(block_id() >= 0); | 468 DCHECK(block_id() >= 0); |
469 | 469 |
470 // Check that the incoming edges are in edge split form. | 470 // Check that the incoming edges are in edge split form. |
471 if (predecessors_.length() > 1) { | 471 if (predecessors_.length() > 1) { |
472 for (int i = 0; i < predecessors_.length(); ++i) { | 472 for (int i = 0; i < predecessors_.length(); ++i) { |
473 ASSERT(predecessors_[i]->end()->SecondSuccessor() == NULL); | 473 DCHECK(predecessors_[i]->end()->SecondSuccessor() == NULL); |
474 } | 474 } |
475 } | 475 } |
476 } | 476 } |
477 #endif | 477 #endif |
478 | 478 |
479 | 479 |
480 void HLoopInformation::RegisterBackEdge(HBasicBlock* block) { | 480 void HLoopInformation::RegisterBackEdge(HBasicBlock* block) { |
481 this->back_edges_.Add(block, block->zone()); | 481 this->back_edges_.Add(block, block->zone()); |
482 AddBlock(block); | 482 AddBlock(block); |
483 } | 483 } |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
566 AllowHandleDereference allow_deref; | 566 AllowHandleDereference allow_deref; |
567 AllowDeferredHandleDereference allow_deferred_deref; | 567 AllowDeferredHandleDereference allow_deferred_deref; |
568 for (int i = 0; i < blocks_.length(); i++) { | 568 for (int i = 0; i < blocks_.length(); i++) { |
569 HBasicBlock* block = blocks_.at(i); | 569 HBasicBlock* block = blocks_.at(i); |
570 | 570 |
571 block->Verify(); | 571 block->Verify(); |
572 | 572 |
573 // Check that every block contains at least one node and that only the last | 573 // Check that every block contains at least one node and that only the last |
574 // node is a control instruction. | 574 // node is a control instruction. |
575 HInstruction* current = block->first(); | 575 HInstruction* current = block->first(); |
576 ASSERT(current != NULL && current->IsBlockEntry()); | 576 DCHECK(current != NULL && current->IsBlockEntry()); |
577 while (current != NULL) { | 577 while (current != NULL) { |
578 ASSERT((current->next() == NULL) == current->IsControlInstruction()); | 578 DCHECK((current->next() == NULL) == current->IsControlInstruction()); |
579 ASSERT(current->block() == block); | 579 DCHECK(current->block() == block); |
580 current->Verify(); | 580 current->Verify(); |
581 current = current->next(); | 581 current = current->next(); |
582 } | 582 } |
583 | 583 |
584 // Check that successors are correctly set. | 584 // Check that successors are correctly set. |
585 HBasicBlock* first = block->end()->FirstSuccessor(); | 585 HBasicBlock* first = block->end()->FirstSuccessor(); |
586 HBasicBlock* second = block->end()->SecondSuccessor(); | 586 HBasicBlock* second = block->end()->SecondSuccessor(); |
587 ASSERT(second == NULL || first != NULL); | 587 DCHECK(second == NULL || first != NULL); |
588 | 588 |
589 // Check that the predecessor array is correct. | 589 // Check that the predecessor array is correct. |
590 if (first != NULL) { | 590 if (first != NULL) { |
591 ASSERT(first->predecessors()->Contains(block)); | 591 DCHECK(first->predecessors()->Contains(block)); |
592 if (second != NULL) { | 592 if (second != NULL) { |
593 ASSERT(second->predecessors()->Contains(block)); | 593 DCHECK(second->predecessors()->Contains(block)); |
594 } | 594 } |
595 } | 595 } |
596 | 596 |
597 // Check that phis have correct arguments. | 597 // Check that phis have correct arguments. |
598 for (int j = 0; j < block->phis()->length(); j++) { | 598 for (int j = 0; j < block->phis()->length(); j++) { |
599 HPhi* phi = block->phis()->at(j); | 599 HPhi* phi = block->phis()->at(j); |
600 phi->Verify(); | 600 phi->Verify(); |
601 } | 601 } |
602 | 602 |
603 // Check that all join blocks have predecessors that end with an | 603 // Check that all join blocks have predecessors that end with an |
604 // unconditional goto and agree on their environment node id. | 604 // unconditional goto and agree on their environment node id. |
605 if (block->predecessors()->length() >= 2) { | 605 if (block->predecessors()->length() >= 2) { |
606 BailoutId id = | 606 BailoutId id = |
607 block->predecessors()->first()->last_environment()->ast_id(); | 607 block->predecessors()->first()->last_environment()->ast_id(); |
608 for (int k = 0; k < block->predecessors()->length(); k++) { | 608 for (int k = 0; k < block->predecessors()->length(); k++) { |
609 HBasicBlock* predecessor = block->predecessors()->at(k); | 609 HBasicBlock* predecessor = block->predecessors()->at(k); |
610 ASSERT(predecessor->end()->IsGoto() || | 610 DCHECK(predecessor->end()->IsGoto() || |
611 predecessor->end()->IsDeoptimize()); | 611 predecessor->end()->IsDeoptimize()); |
612 ASSERT(predecessor->last_environment()->ast_id() == id); | 612 DCHECK(predecessor->last_environment()->ast_id() == id); |
613 } | 613 } |
614 } | 614 } |
615 } | 615 } |
616 | 616 |
617 // Check special property of first block to have no predecessors. | 617 // Check special property of first block to have no predecessors. |
618 ASSERT(blocks_.at(0)->predecessors()->is_empty()); | 618 DCHECK(blocks_.at(0)->predecessors()->is_empty()); |
619 | 619 |
620 if (do_full_verify) { | 620 if (do_full_verify) { |
621 // Check that the graph is fully connected. | 621 // Check that the graph is fully connected. |
622 ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(), NULL); | 622 ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(), NULL); |
623 ASSERT(analyzer.visited_count() == blocks_.length()); | 623 DCHECK(analyzer.visited_count() == blocks_.length()); |
624 | 624 |
625 // Check that entry block dominator is NULL. | 625 // Check that entry block dominator is NULL. |
626 ASSERT(entry_block_->dominator() == NULL); | 626 DCHECK(entry_block_->dominator() == NULL); |
627 | 627 |
628 // Check dominators. | 628 // Check dominators. |
629 for (int i = 0; i < blocks_.length(); ++i) { | 629 for (int i = 0; i < blocks_.length(); ++i) { |
630 HBasicBlock* block = blocks_.at(i); | 630 HBasicBlock* block = blocks_.at(i); |
631 if (block->dominator() == NULL) { | 631 if (block->dominator() == NULL) { |
632 // Only start block may have no dominator assigned to. | 632 // Only start block may have no dominator assigned to. |
633 ASSERT(i == 0); | 633 DCHECK(i == 0); |
634 } else { | 634 } else { |
635 // Assert that block is unreachable if dominator must not be visited. | 635 // Assert that block is unreachable if dominator must not be visited. |
636 ReachabilityAnalyzer dominator_analyzer(entry_block_, | 636 ReachabilityAnalyzer dominator_analyzer(entry_block_, |
637 blocks_.length(), | 637 blocks_.length(), |
638 block->dominator()); | 638 block->dominator()); |
639 ASSERT(!dominator_analyzer.reachable()->Contains(block->block_id())); | 639 DCHECK(!dominator_analyzer.reachable()->Contains(block->block_id())); |
640 } | 640 } |
641 } | 641 } |
642 } | 642 } |
643 } | 643 } |
644 | 644 |
645 #endif | 645 #endif |
646 | 646 |
647 | 647 |
648 HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer, | 648 HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer, |
649 int32_t value) { | 649 int32_t value) { |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
785 void HGraphBuilder::IfBuilder::Initialize(HGraphBuilder* builder) { | 785 void HGraphBuilder::IfBuilder::Initialize(HGraphBuilder* builder) { |
786 InitializeDontCreateBlocks(builder); | 786 InitializeDontCreateBlocks(builder); |
787 HEnvironment* env = builder->environment(); | 787 HEnvironment* env = builder->environment(); |
788 first_true_block_ = builder->CreateBasicBlock(env->Copy()); | 788 first_true_block_ = builder->CreateBasicBlock(env->Copy()); |
789 first_false_block_ = builder->CreateBasicBlock(env->Copy()); | 789 first_false_block_ = builder->CreateBasicBlock(env->Copy()); |
790 } | 790 } |
791 | 791 |
792 | 792 |
793 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare( | 793 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare( |
794 HControlInstruction* compare) { | 794 HControlInstruction* compare) { |
795 ASSERT(did_then_ == did_else_); | 795 DCHECK(did_then_ == did_else_); |
796 if (did_else_) { | 796 if (did_else_) { |
797 // Handle if-then-elseif | 797 // Handle if-then-elseif |
798 did_else_if_ = true; | 798 did_else_if_ = true; |
799 did_else_ = false; | 799 did_else_ = false; |
800 did_then_ = false; | 800 did_then_ = false; |
801 did_and_ = false; | 801 did_and_ = false; |
802 did_or_ = false; | 802 did_or_ = false; |
803 pending_merge_block_ = false; | 803 pending_merge_block_ = false; |
804 split_edge_merge_block_ = NULL; | 804 split_edge_merge_block_ = NULL; |
805 HEnvironment* env = builder()->environment(); | 805 HEnvironment* env = builder()->environment(); |
(...skipping 15 matching lines...) Expand all Loading... |
821 compare->SetSuccessorAt(0, first_true_block_); | 821 compare->SetSuccessorAt(0, first_true_block_); |
822 compare->SetSuccessorAt(1, first_false_block_); | 822 compare->SetSuccessorAt(1, first_false_block_); |
823 } | 823 } |
824 builder()->FinishCurrentBlock(compare); | 824 builder()->FinishCurrentBlock(compare); |
825 needs_compare_ = false; | 825 needs_compare_ = false; |
826 return compare; | 826 return compare; |
827 } | 827 } |
828 | 828 |
829 | 829 |
830 void HGraphBuilder::IfBuilder::Or() { | 830 void HGraphBuilder::IfBuilder::Or() { |
831 ASSERT(!needs_compare_); | 831 DCHECK(!needs_compare_); |
832 ASSERT(!did_and_); | 832 DCHECK(!did_and_); |
833 did_or_ = true; | 833 did_or_ = true; |
834 HEnvironment* env = first_false_block_->last_environment(); | 834 HEnvironment* env = first_false_block_->last_environment(); |
835 if (split_edge_merge_block_ == NULL) { | 835 if (split_edge_merge_block_ == NULL) { |
836 split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy()); | 836 split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy()); |
837 builder()->GotoNoSimulate(first_true_block_, split_edge_merge_block_); | 837 builder()->GotoNoSimulate(first_true_block_, split_edge_merge_block_); |
838 first_true_block_ = split_edge_merge_block_; | 838 first_true_block_ = split_edge_merge_block_; |
839 } | 839 } |
840 builder()->set_current_block(first_false_block_); | 840 builder()->set_current_block(first_false_block_); |
841 first_false_block_ = builder()->CreateBasicBlock(env->Copy()); | 841 first_false_block_ = builder()->CreateBasicBlock(env->Copy()); |
842 } | 842 } |
843 | 843 |
844 | 844 |
845 void HGraphBuilder::IfBuilder::And() { | 845 void HGraphBuilder::IfBuilder::And() { |
846 ASSERT(!needs_compare_); | 846 DCHECK(!needs_compare_); |
847 ASSERT(!did_or_); | 847 DCHECK(!did_or_); |
848 did_and_ = true; | 848 did_and_ = true; |
849 HEnvironment* env = first_false_block_->last_environment(); | 849 HEnvironment* env = first_false_block_->last_environment(); |
850 if (split_edge_merge_block_ == NULL) { | 850 if (split_edge_merge_block_ == NULL) { |
851 split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy()); | 851 split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy()); |
852 builder()->GotoNoSimulate(first_false_block_, split_edge_merge_block_); | 852 builder()->GotoNoSimulate(first_false_block_, split_edge_merge_block_); |
853 first_false_block_ = split_edge_merge_block_; | 853 first_false_block_ = split_edge_merge_block_; |
854 } | 854 } |
855 builder()->set_current_block(first_true_block_); | 855 builder()->set_current_block(first_true_block_); |
856 first_true_block_ = builder()->CreateBasicBlock(env->Copy()); | 856 first_true_block_ = builder()->CreateBasicBlock(env->Copy()); |
857 } | 857 } |
858 | 858 |
859 | 859 |
860 void HGraphBuilder::IfBuilder::CaptureContinuation( | 860 void HGraphBuilder::IfBuilder::CaptureContinuation( |
861 HIfContinuation* continuation) { | 861 HIfContinuation* continuation) { |
862 ASSERT(!did_else_if_); | 862 DCHECK(!did_else_if_); |
863 ASSERT(!finished_); | 863 DCHECK(!finished_); |
864 ASSERT(!captured_); | 864 DCHECK(!captured_); |
865 | 865 |
866 HBasicBlock* true_block = NULL; | 866 HBasicBlock* true_block = NULL; |
867 HBasicBlock* false_block = NULL; | 867 HBasicBlock* false_block = NULL; |
868 Finish(&true_block, &false_block); | 868 Finish(&true_block, &false_block); |
869 ASSERT(true_block != NULL); | 869 DCHECK(true_block != NULL); |
870 ASSERT(false_block != NULL); | 870 DCHECK(false_block != NULL); |
871 continuation->Capture(true_block, false_block); | 871 continuation->Capture(true_block, false_block); |
872 captured_ = true; | 872 captured_ = true; |
873 builder()->set_current_block(NULL); | 873 builder()->set_current_block(NULL); |
874 End(); | 874 End(); |
875 } | 875 } |
876 | 876 |
877 | 877 |
878 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) { | 878 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) { |
879 ASSERT(!did_else_if_); | 879 DCHECK(!did_else_if_); |
880 ASSERT(!finished_); | 880 DCHECK(!finished_); |
881 ASSERT(!captured_); | 881 DCHECK(!captured_); |
882 HBasicBlock* true_block = NULL; | 882 HBasicBlock* true_block = NULL; |
883 HBasicBlock* false_block = NULL; | 883 HBasicBlock* false_block = NULL; |
884 Finish(&true_block, &false_block); | 884 Finish(&true_block, &false_block); |
885 merge_at_join_blocks_ = NULL; | 885 merge_at_join_blocks_ = NULL; |
886 if (true_block != NULL && !true_block->IsFinished()) { | 886 if (true_block != NULL && !true_block->IsFinished()) { |
887 ASSERT(continuation->IsTrueReachable()); | 887 DCHECK(continuation->IsTrueReachable()); |
888 builder()->GotoNoSimulate(true_block, continuation->true_branch()); | 888 builder()->GotoNoSimulate(true_block, continuation->true_branch()); |
889 } | 889 } |
890 if (false_block != NULL && !false_block->IsFinished()) { | 890 if (false_block != NULL && !false_block->IsFinished()) { |
891 ASSERT(continuation->IsFalseReachable()); | 891 DCHECK(continuation->IsFalseReachable()); |
892 builder()->GotoNoSimulate(false_block, continuation->false_branch()); | 892 builder()->GotoNoSimulate(false_block, continuation->false_branch()); |
893 } | 893 } |
894 captured_ = true; | 894 captured_ = true; |
895 End(); | 895 End(); |
896 } | 896 } |
897 | 897 |
898 | 898 |
899 void HGraphBuilder::IfBuilder::Then() { | 899 void HGraphBuilder::IfBuilder::Then() { |
900 ASSERT(!captured_); | 900 DCHECK(!captured_); |
901 ASSERT(!finished_); | 901 DCHECK(!finished_); |
902 did_then_ = true; | 902 did_then_ = true; |
903 if (needs_compare_) { | 903 if (needs_compare_) { |
904 // Handle if's without any expressions, they jump directly to the "else" | 904 // Handle if's without any expressions, they jump directly to the "else" |
905 // branch. However, we must pretend that the "then" branch is reachable, | 905 // branch. However, we must pretend that the "then" branch is reachable, |
906 // so that the graph builder visits it and sees any live range extending | 906 // so that the graph builder visits it and sees any live range extending |
907 // constructs within it. | 907 // constructs within it. |
908 HConstant* constant_false = builder()->graph()->GetConstantFalse(); | 908 HConstant* constant_false = builder()->graph()->GetConstantFalse(); |
909 ToBooleanStub::Types boolean_type = ToBooleanStub::Types(); | 909 ToBooleanStub::Types boolean_type = ToBooleanStub::Types(); |
910 boolean_type.Add(ToBooleanStub::BOOLEAN); | 910 boolean_type.Add(ToBooleanStub::BOOLEAN); |
911 HBranch* branch = builder()->New<HBranch>( | 911 HBranch* branch = builder()->New<HBranch>( |
912 constant_false, boolean_type, first_true_block_, first_false_block_); | 912 constant_false, boolean_type, first_true_block_, first_false_block_); |
913 builder()->FinishCurrentBlock(branch); | 913 builder()->FinishCurrentBlock(branch); |
914 } | 914 } |
915 builder()->set_current_block(first_true_block_); | 915 builder()->set_current_block(first_true_block_); |
916 pending_merge_block_ = true; | 916 pending_merge_block_ = true; |
917 } | 917 } |
918 | 918 |
919 | 919 |
920 void HGraphBuilder::IfBuilder::Else() { | 920 void HGraphBuilder::IfBuilder::Else() { |
921 ASSERT(did_then_); | 921 DCHECK(did_then_); |
922 ASSERT(!captured_); | 922 DCHECK(!captured_); |
923 ASSERT(!finished_); | 923 DCHECK(!finished_); |
924 AddMergeAtJoinBlock(false); | 924 AddMergeAtJoinBlock(false); |
925 builder()->set_current_block(first_false_block_); | 925 builder()->set_current_block(first_false_block_); |
926 pending_merge_block_ = true; | 926 pending_merge_block_ = true; |
927 did_else_ = true; | 927 did_else_ = true; |
928 } | 928 } |
929 | 929 |
930 | 930 |
931 void HGraphBuilder::IfBuilder::Deopt(const char* reason) { | 931 void HGraphBuilder::IfBuilder::Deopt(const char* reason) { |
932 ASSERT(did_then_); | 932 DCHECK(did_then_); |
933 builder()->Add<HDeoptimize>(reason, Deoptimizer::EAGER); | 933 builder()->Add<HDeoptimize>(reason, Deoptimizer::EAGER); |
934 AddMergeAtJoinBlock(true); | 934 AddMergeAtJoinBlock(true); |
935 } | 935 } |
936 | 936 |
937 | 937 |
938 void HGraphBuilder::IfBuilder::Return(HValue* value) { | 938 void HGraphBuilder::IfBuilder::Return(HValue* value) { |
939 HValue* parameter_count = builder()->graph()->GetConstantMinus1(); | 939 HValue* parameter_count = builder()->graph()->GetConstantMinus1(); |
940 builder()->FinishExitCurrentBlock( | 940 builder()->FinishExitCurrentBlock( |
941 builder()->New<HReturn>(value, parameter_count)); | 941 builder()->New<HReturn>(value, parameter_count)); |
942 AddMergeAtJoinBlock(false); | 942 AddMergeAtJoinBlock(false); |
943 } | 943 } |
944 | 944 |
945 | 945 |
946 void HGraphBuilder::IfBuilder::AddMergeAtJoinBlock(bool deopt) { | 946 void HGraphBuilder::IfBuilder::AddMergeAtJoinBlock(bool deopt) { |
947 if (!pending_merge_block_) return; | 947 if (!pending_merge_block_) return; |
948 HBasicBlock* block = builder()->current_block(); | 948 HBasicBlock* block = builder()->current_block(); |
949 ASSERT(block == NULL || !block->IsFinished()); | 949 DCHECK(block == NULL || !block->IsFinished()); |
950 MergeAtJoinBlock* record = new (builder()->zone()) | 950 MergeAtJoinBlock* record = new (builder()->zone()) |
951 MergeAtJoinBlock(block, deopt, merge_at_join_blocks_); | 951 MergeAtJoinBlock(block, deopt, merge_at_join_blocks_); |
952 merge_at_join_blocks_ = record; | 952 merge_at_join_blocks_ = record; |
953 if (block != NULL) { | 953 if (block != NULL) { |
954 ASSERT(block->end() == NULL); | 954 DCHECK(block->end() == NULL); |
955 if (deopt) { | 955 if (deopt) { |
956 normal_merge_at_join_block_count_++; | 956 normal_merge_at_join_block_count_++; |
957 } else { | 957 } else { |
958 deopt_merge_at_join_block_count_++; | 958 deopt_merge_at_join_block_count_++; |
959 } | 959 } |
960 } | 960 } |
961 builder()->set_current_block(NULL); | 961 builder()->set_current_block(NULL); |
962 pending_merge_block_ = false; | 962 pending_merge_block_ = false; |
963 } | 963 } |
964 | 964 |
965 | 965 |
966 void HGraphBuilder::IfBuilder::Finish() { | 966 void HGraphBuilder::IfBuilder::Finish() { |
967 ASSERT(!finished_); | 967 DCHECK(!finished_); |
968 if (!did_then_) { | 968 if (!did_then_) { |
969 Then(); | 969 Then(); |
970 } | 970 } |
971 AddMergeAtJoinBlock(false); | 971 AddMergeAtJoinBlock(false); |
972 if (!did_else_) { | 972 if (!did_else_) { |
973 Else(); | 973 Else(); |
974 AddMergeAtJoinBlock(false); | 974 AddMergeAtJoinBlock(false); |
975 } | 975 } |
976 finished_ = true; | 976 finished_ = true; |
977 } | 977 } |
978 | 978 |
979 | 979 |
980 void HGraphBuilder::IfBuilder::Finish(HBasicBlock** then_continuation, | 980 void HGraphBuilder::IfBuilder::Finish(HBasicBlock** then_continuation, |
981 HBasicBlock** else_continuation) { | 981 HBasicBlock** else_continuation) { |
982 Finish(); | 982 Finish(); |
983 | 983 |
984 MergeAtJoinBlock* else_record = merge_at_join_blocks_; | 984 MergeAtJoinBlock* else_record = merge_at_join_blocks_; |
985 if (else_continuation != NULL) { | 985 if (else_continuation != NULL) { |
986 *else_continuation = else_record->block_; | 986 *else_continuation = else_record->block_; |
987 } | 987 } |
988 MergeAtJoinBlock* then_record = else_record->next_; | 988 MergeAtJoinBlock* then_record = else_record->next_; |
989 if (then_continuation != NULL) { | 989 if (then_continuation != NULL) { |
990 *then_continuation = then_record->block_; | 990 *then_continuation = then_record->block_; |
991 } | 991 } |
992 ASSERT(then_record->next_ == NULL); | 992 DCHECK(then_record->next_ == NULL); |
993 } | 993 } |
994 | 994 |
995 | 995 |
996 void HGraphBuilder::IfBuilder::End() { | 996 void HGraphBuilder::IfBuilder::End() { |
997 if (captured_) return; | 997 if (captured_) return; |
998 Finish(); | 998 Finish(); |
999 | 999 |
1000 int total_merged_blocks = normal_merge_at_join_block_count_ + | 1000 int total_merged_blocks = normal_merge_at_join_block_count_ + |
1001 deopt_merge_at_join_block_count_; | 1001 deopt_merge_at_join_block_count_; |
1002 ASSERT(total_merged_blocks >= 1); | 1002 DCHECK(total_merged_blocks >= 1); |
1003 HBasicBlock* merge_block = | 1003 HBasicBlock* merge_block = |
1004 total_merged_blocks == 1 ? NULL : builder()->graph()->CreateBasicBlock(); | 1004 total_merged_blocks == 1 ? NULL : builder()->graph()->CreateBasicBlock(); |
1005 | 1005 |
1006 // Merge non-deopt blocks first to ensure environment has right size for | 1006 // Merge non-deopt blocks first to ensure environment has right size for |
1007 // padding. | 1007 // padding. |
1008 MergeAtJoinBlock* current = merge_at_join_blocks_; | 1008 MergeAtJoinBlock* current = merge_at_join_blocks_; |
1009 while (current != NULL) { | 1009 while (current != NULL) { |
1010 if (!current->deopt_ && current->block_ != NULL) { | 1010 if (!current->deopt_ && current->block_ != NULL) { |
1011 // If there is only one block that makes it through to the end of the | 1011 // If there is only one block that makes it through to the end of the |
1012 // if, then just set it as the current block and continue rather then | 1012 // if, then just set it as the current block and continue rather then |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1066 body_block_ = NULL; | 1066 body_block_ = NULL; |
1067 exit_block_ = NULL; | 1067 exit_block_ = NULL; |
1068 exit_trampoline_block_ = NULL; | 1068 exit_trampoline_block_ = NULL; |
1069 } | 1069 } |
1070 | 1070 |
1071 | 1071 |
1072 HValue* HGraphBuilder::LoopBuilder::BeginBody( | 1072 HValue* HGraphBuilder::LoopBuilder::BeginBody( |
1073 HValue* initial, | 1073 HValue* initial, |
1074 HValue* terminating, | 1074 HValue* terminating, |
1075 Token::Value token) { | 1075 Token::Value token) { |
1076 ASSERT(direction_ != kWhileTrue); | 1076 DCHECK(direction_ != kWhileTrue); |
1077 HEnvironment* env = builder_->environment(); | 1077 HEnvironment* env = builder_->environment(); |
1078 phi_ = header_block_->AddNewPhi(env->values()->length()); | 1078 phi_ = header_block_->AddNewPhi(env->values()->length()); |
1079 phi_->AddInput(initial); | 1079 phi_->AddInput(initial); |
1080 env->Push(initial); | 1080 env->Push(initial); |
1081 builder_->GotoNoSimulate(header_block_); | 1081 builder_->GotoNoSimulate(header_block_); |
1082 | 1082 |
1083 HEnvironment* body_env = env->Copy(); | 1083 HEnvironment* body_env = env->Copy(); |
1084 HEnvironment* exit_env = env->Copy(); | 1084 HEnvironment* exit_env = env->Copy(); |
1085 // Remove the phi from the expression stack | 1085 // Remove the phi from the expression stack |
1086 body_env->Pop(); | 1086 body_env->Pop(); |
(...skipping 17 matching lines...) Expand all Loading... |
1104 increment_->ClearFlag(HValue::kCanOverflow); | 1104 increment_->ClearFlag(HValue::kCanOverflow); |
1105 builder_->AddInstruction(increment_); | 1105 builder_->AddInstruction(increment_); |
1106 return increment_; | 1106 return increment_; |
1107 } else { | 1107 } else { |
1108 return phi_; | 1108 return phi_; |
1109 } | 1109 } |
1110 } | 1110 } |
1111 | 1111 |
1112 | 1112 |
1113 void HGraphBuilder::LoopBuilder::BeginBody(int drop_count) { | 1113 void HGraphBuilder::LoopBuilder::BeginBody(int drop_count) { |
1114 ASSERT(direction_ == kWhileTrue); | 1114 DCHECK(direction_ == kWhileTrue); |
1115 HEnvironment* env = builder_->environment(); | 1115 HEnvironment* env = builder_->environment(); |
1116 builder_->GotoNoSimulate(header_block_); | 1116 builder_->GotoNoSimulate(header_block_); |
1117 builder_->set_current_block(header_block_); | 1117 builder_->set_current_block(header_block_); |
1118 env->Drop(drop_count); | 1118 env->Drop(drop_count); |
1119 } | 1119 } |
1120 | 1120 |
1121 | 1121 |
1122 void HGraphBuilder::LoopBuilder::Break() { | 1122 void HGraphBuilder::LoopBuilder::Break() { |
1123 if (exit_trampoline_block_ == NULL) { | 1123 if (exit_trampoline_block_ == NULL) { |
1124 // Its the first time we saw a break. | 1124 // Its the first time we saw a break. |
1125 if (direction_ == kWhileTrue) { | 1125 if (direction_ == kWhileTrue) { |
1126 HEnvironment* env = builder_->environment()->Copy(); | 1126 HEnvironment* env = builder_->environment()->Copy(); |
1127 exit_trampoline_block_ = builder_->CreateBasicBlock(env); | 1127 exit_trampoline_block_ = builder_->CreateBasicBlock(env); |
1128 } else { | 1128 } else { |
1129 HEnvironment* env = exit_block_->last_environment()->Copy(); | 1129 HEnvironment* env = exit_block_->last_environment()->Copy(); |
1130 exit_trampoline_block_ = builder_->CreateBasicBlock(env); | 1130 exit_trampoline_block_ = builder_->CreateBasicBlock(env); |
1131 builder_->GotoNoSimulate(exit_block_, exit_trampoline_block_); | 1131 builder_->GotoNoSimulate(exit_block_, exit_trampoline_block_); |
1132 } | 1132 } |
1133 } | 1133 } |
1134 | 1134 |
1135 builder_->GotoNoSimulate(exit_trampoline_block_); | 1135 builder_->GotoNoSimulate(exit_trampoline_block_); |
1136 builder_->set_current_block(NULL); | 1136 builder_->set_current_block(NULL); |
1137 } | 1137 } |
1138 | 1138 |
1139 | 1139 |
1140 void HGraphBuilder::LoopBuilder::EndBody() { | 1140 void HGraphBuilder::LoopBuilder::EndBody() { |
1141 ASSERT(!finished_); | 1141 DCHECK(!finished_); |
1142 | 1142 |
1143 if (direction_ == kPostIncrement || direction_ == kPostDecrement) { | 1143 if (direction_ == kPostIncrement || direction_ == kPostDecrement) { |
1144 if (direction_ == kPostIncrement) { | 1144 if (direction_ == kPostIncrement) { |
1145 increment_ = HAdd::New(zone(), context_, phi_, increment_amount_); | 1145 increment_ = HAdd::New(zone(), context_, phi_, increment_amount_); |
1146 } else { | 1146 } else { |
1147 increment_ = HSub::New(zone(), context_, phi_, increment_amount_); | 1147 increment_ = HSub::New(zone(), context_, phi_, increment_amount_); |
1148 } | 1148 } |
1149 increment_->ClearFlag(HValue::kCanOverflow); | 1149 increment_->ClearFlag(HValue::kCanOverflow); |
1150 builder_->AddInstruction(increment_); | 1150 builder_->AddInstruction(increment_); |
1151 } | 1151 } |
(...skipping 21 matching lines...) Expand all Loading... |
1173 if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_); | 1173 if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_); |
1174 CompilationPhase phase("H_Block building", info_); | 1174 CompilationPhase phase("H_Block building", info_); |
1175 set_current_block(graph()->entry_block()); | 1175 set_current_block(graph()->entry_block()); |
1176 if (!BuildGraph()) return NULL; | 1176 if (!BuildGraph()) return NULL; |
1177 graph()->FinalizeUniqueness(); | 1177 graph()->FinalizeUniqueness(); |
1178 return graph_; | 1178 return graph_; |
1179 } | 1179 } |
1180 | 1180 |
1181 | 1181 |
1182 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { | 1182 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { |
1183 ASSERT(current_block() != NULL); | 1183 DCHECK(current_block() != NULL); |
1184 ASSERT(!FLAG_hydrogen_track_positions || | 1184 DCHECK(!FLAG_hydrogen_track_positions || |
1185 !position_.IsUnknown() || | 1185 !position_.IsUnknown() || |
1186 !info_->IsOptimizing()); | 1186 !info_->IsOptimizing()); |
1187 current_block()->AddInstruction(instr, source_position()); | 1187 current_block()->AddInstruction(instr, source_position()); |
1188 if (graph()->IsInsideNoSideEffectsScope()) { | 1188 if (graph()->IsInsideNoSideEffectsScope()) { |
1189 instr->SetFlag(HValue::kHasNoObservableSideEffects); | 1189 instr->SetFlag(HValue::kHasNoObservableSideEffects); |
1190 } | 1190 } |
1191 return instr; | 1191 return instr; |
1192 } | 1192 } |
1193 | 1193 |
1194 | 1194 |
1195 void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) { | 1195 void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) { |
1196 ASSERT(!FLAG_hydrogen_track_positions || | 1196 DCHECK(!FLAG_hydrogen_track_positions || |
1197 !info_->IsOptimizing() || | 1197 !info_->IsOptimizing() || |
1198 !position_.IsUnknown()); | 1198 !position_.IsUnknown()); |
1199 current_block()->Finish(last, source_position()); | 1199 current_block()->Finish(last, source_position()); |
1200 if (last->IsReturn() || last->IsAbnormalExit()) { | 1200 if (last->IsReturn() || last->IsAbnormalExit()) { |
1201 set_current_block(NULL); | 1201 set_current_block(NULL); |
1202 } | 1202 } |
1203 } | 1203 } |
1204 | 1204 |
1205 | 1205 |
1206 void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) { | 1206 void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) { |
1207 ASSERT(!FLAG_hydrogen_track_positions || !info_->IsOptimizing() || | 1207 DCHECK(!FLAG_hydrogen_track_positions || !info_->IsOptimizing() || |
1208 !position_.IsUnknown()); | 1208 !position_.IsUnknown()); |
1209 current_block()->FinishExit(instruction, source_position()); | 1209 current_block()->FinishExit(instruction, source_position()); |
1210 if (instruction->IsReturn() || instruction->IsAbnormalExit()) { | 1210 if (instruction->IsReturn() || instruction->IsAbnormalExit()) { |
1211 set_current_block(NULL); | 1211 set_current_block(NULL); |
1212 } | 1212 } |
1213 } | 1213 } |
1214 | 1214 |
1215 | 1215 |
1216 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) { | 1216 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) { |
1217 if (FLAG_native_code_counters && counter->Enabled()) { | 1217 if (FLAG_native_code_counters && counter->Enabled()) { |
1218 HValue* reference = Add<HConstant>(ExternalReference(counter)); | 1218 HValue* reference = Add<HConstant>(ExternalReference(counter)); |
1219 HValue* old_value = Add<HLoadNamedField>( | 1219 HValue* old_value = Add<HLoadNamedField>( |
1220 reference, static_cast<HValue*>(NULL), HObjectAccess::ForCounter()); | 1220 reference, static_cast<HValue*>(NULL), HObjectAccess::ForCounter()); |
1221 HValue* new_value = AddUncasted<HAdd>(old_value, graph()->GetConstant1()); | 1221 HValue* new_value = AddUncasted<HAdd>(old_value, graph()->GetConstant1()); |
1222 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow | 1222 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow |
1223 Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(), | 1223 Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(), |
1224 new_value, STORE_TO_INITIALIZED_ENTRY); | 1224 new_value, STORE_TO_INITIALIZED_ENTRY); |
1225 } | 1225 } |
1226 } | 1226 } |
1227 | 1227 |
1228 | 1228 |
1229 void HGraphBuilder::AddSimulate(BailoutId id, | 1229 void HGraphBuilder::AddSimulate(BailoutId id, |
1230 RemovableSimulate removable) { | 1230 RemovableSimulate removable) { |
1231 ASSERT(current_block() != NULL); | 1231 DCHECK(current_block() != NULL); |
1232 ASSERT(!graph()->IsInsideNoSideEffectsScope()); | 1232 DCHECK(!graph()->IsInsideNoSideEffectsScope()); |
1233 current_block()->AddNewSimulate(id, source_position(), removable); | 1233 current_block()->AddNewSimulate(id, source_position(), removable); |
1234 } | 1234 } |
1235 | 1235 |
1236 | 1236 |
1237 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { | 1237 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { |
1238 HBasicBlock* b = graph()->CreateBasicBlock(); | 1238 HBasicBlock* b = graph()->CreateBasicBlock(); |
1239 b->SetInitialEnvironment(env); | 1239 b->SetInitialEnvironment(env); |
1240 return b; | 1240 return b; |
1241 } | 1241 } |
1242 | 1242 |
(...skipping 24 matching lines...) Expand all Loading... |
1267 | 1267 |
1268 | 1268 |
1269 void HGraphBuilder::FinishExitWithHardDeoptimization(const char* reason) { | 1269 void HGraphBuilder::FinishExitWithHardDeoptimization(const char* reason) { |
1270 Add<HDeoptimize>(reason, Deoptimizer::EAGER); | 1270 Add<HDeoptimize>(reason, Deoptimizer::EAGER); |
1271 FinishExitCurrentBlock(New<HAbnormalExit>()); | 1271 FinishExitCurrentBlock(New<HAbnormalExit>()); |
1272 } | 1272 } |
1273 | 1273 |
1274 | 1274 |
1275 HValue* HGraphBuilder::BuildCheckString(HValue* string) { | 1275 HValue* HGraphBuilder::BuildCheckString(HValue* string) { |
1276 if (!string->type().IsString()) { | 1276 if (!string->type().IsString()) { |
1277 ASSERT(!string->IsConstant() || | 1277 DCHECK(!string->IsConstant() || |
1278 !HConstant::cast(string)->HasStringValue()); | 1278 !HConstant::cast(string)->HasStringValue()); |
1279 BuildCheckHeapObject(string); | 1279 BuildCheckHeapObject(string); |
1280 return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING); | 1280 return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING); |
1281 } | 1281 } |
1282 return string; | 1282 return string; |
1283 } | 1283 } |
1284 | 1284 |
1285 | 1285 |
1286 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) { | 1286 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) { |
1287 if (object->type().IsJSObject()) return object; | 1287 if (object->type().IsJSObject()) return object; |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1386 | 1386 |
1387 return environment()->Pop(); | 1387 return environment()->Pop(); |
1388 } | 1388 } |
1389 | 1389 |
1390 | 1390 |
1391 void HGraphBuilder::BuildTransitionElementsKind(HValue* object, | 1391 void HGraphBuilder::BuildTransitionElementsKind(HValue* object, |
1392 HValue* map, | 1392 HValue* map, |
1393 ElementsKind from_kind, | 1393 ElementsKind from_kind, |
1394 ElementsKind to_kind, | 1394 ElementsKind to_kind, |
1395 bool is_jsarray) { | 1395 bool is_jsarray) { |
1396 ASSERT(!IsFastHoleyElementsKind(from_kind) || | 1396 DCHECK(!IsFastHoleyElementsKind(from_kind) || |
1397 IsFastHoleyElementsKind(to_kind)); | 1397 IsFastHoleyElementsKind(to_kind)); |
1398 | 1398 |
1399 if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) { | 1399 if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) { |
1400 Add<HTrapAllocationMemento>(object); | 1400 Add<HTrapAllocationMemento>(object); |
1401 } | 1401 } |
1402 | 1402 |
1403 if (!IsSimpleMapChangeTransition(from_kind, to_kind)) { | 1403 if (!IsSimpleMapChangeTransition(from_kind, to_kind)) { |
1404 HInstruction* elements = AddLoadElements(object); | 1404 HInstruction* elements = AddLoadElements(object); |
1405 | 1405 |
1406 HInstruction* empty_fixed_array = Add<HConstant>( | 1406 HInstruction* empty_fixed_array = Add<HConstant>( |
(...skipping 652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2059 HValue* right, | 2059 HValue* right, |
2060 HAllocationMode allocation_mode) { | 2060 HAllocationMode allocation_mode) { |
2061 // Determine the string instance types. | 2061 // Determine the string instance types. |
2062 HInstruction* left_instance_type = AddLoadStringInstanceType(left); | 2062 HInstruction* left_instance_type = AddLoadStringInstanceType(left); |
2063 HInstruction* right_instance_type = AddLoadStringInstanceType(right); | 2063 HInstruction* right_instance_type = AddLoadStringInstanceType(right); |
2064 | 2064 |
2065 // Allocate the cons string object. HAllocate does not care whether we | 2065 // Allocate the cons string object. HAllocate does not care whether we |
2066 // pass CONS_STRING_TYPE or CONS_ASCII_STRING_TYPE here, so we just use | 2066 // pass CONS_STRING_TYPE or CONS_ASCII_STRING_TYPE here, so we just use |
2067 // CONS_STRING_TYPE here. Below we decide whether the cons string is | 2067 // CONS_STRING_TYPE here. Below we decide whether the cons string is |
2068 // one-byte or two-byte and set the appropriate map. | 2068 // one-byte or two-byte and set the appropriate map. |
2069 ASSERT(HAllocate::CompatibleInstanceTypes(CONS_STRING_TYPE, | 2069 DCHECK(HAllocate::CompatibleInstanceTypes(CONS_STRING_TYPE, |
2070 CONS_ASCII_STRING_TYPE)); | 2070 CONS_ASCII_STRING_TYPE)); |
2071 HAllocate* result = BuildAllocate(Add<HConstant>(ConsString::kSize), | 2071 HAllocate* result = BuildAllocate(Add<HConstant>(ConsString::kSize), |
2072 HType::String(), CONS_STRING_TYPE, | 2072 HType::String(), CONS_STRING_TYPE, |
2073 allocation_mode); | 2073 allocation_mode); |
2074 | 2074 |
2075 // Compute intersection and difference of instance types. | 2075 // Compute intersection and difference of instance types. |
2076 HValue* anded_instance_types = AddUncasted<HBitwise>( | 2076 HValue* anded_instance_types = AddUncasted<HBitwise>( |
2077 Token::BIT_AND, left_instance_type, right_instance_type); | 2077 Token::BIT_AND, left_instance_type, right_instance_type); |
2078 HValue* xored_instance_types = AddUncasted<HBitwise>( | 2078 HValue* xored_instance_types = AddUncasted<HBitwise>( |
2079 Token::BIT_XOR, left_instance_type, right_instance_type); | 2079 Token::BIT_XOR, left_instance_type, right_instance_type); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2137 } | 2137 } |
2138 | 2138 |
2139 | 2139 |
2140 void HGraphBuilder::BuildCopySeqStringChars(HValue* src, | 2140 void HGraphBuilder::BuildCopySeqStringChars(HValue* src, |
2141 HValue* src_offset, | 2141 HValue* src_offset, |
2142 String::Encoding src_encoding, | 2142 String::Encoding src_encoding, |
2143 HValue* dst, | 2143 HValue* dst, |
2144 HValue* dst_offset, | 2144 HValue* dst_offset, |
2145 String::Encoding dst_encoding, | 2145 String::Encoding dst_encoding, |
2146 HValue* length) { | 2146 HValue* length) { |
2147 ASSERT(dst_encoding != String::ONE_BYTE_ENCODING || | 2147 DCHECK(dst_encoding != String::ONE_BYTE_ENCODING || |
2148 src_encoding == String::ONE_BYTE_ENCODING); | 2148 src_encoding == String::ONE_BYTE_ENCODING); |
2149 LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement); | 2149 LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement); |
2150 HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT); | 2150 HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT); |
2151 { | 2151 { |
2152 HValue* src_index = AddUncasted<HAdd>(src_offset, index); | 2152 HValue* src_index = AddUncasted<HAdd>(src_offset, index); |
2153 HValue* value = | 2153 HValue* value = |
2154 AddUncasted<HSeqStringGetChar>(src_encoding, src, src_index); | 2154 AddUncasted<HSeqStringGetChar>(src_encoding, src, src_index); |
2155 HValue* dst_index = AddUncasted<HAdd>(dst_offset, index); | 2155 HValue* dst_index = AddUncasted<HAdd>(dst_offset, index); |
2156 Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value); | 2156 Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value); |
2157 } | 2157 } |
2158 loop.EndBody(); | 2158 loop.EndBody(); |
2159 } | 2159 } |
2160 | 2160 |
2161 | 2161 |
2162 HValue* HGraphBuilder::BuildObjectSizeAlignment( | 2162 HValue* HGraphBuilder::BuildObjectSizeAlignment( |
2163 HValue* unaligned_size, int header_size) { | 2163 HValue* unaligned_size, int header_size) { |
2164 ASSERT((header_size & kObjectAlignmentMask) == 0); | 2164 DCHECK((header_size & kObjectAlignmentMask) == 0); |
2165 HValue* size = AddUncasted<HAdd>( | 2165 HValue* size = AddUncasted<HAdd>( |
2166 unaligned_size, Add<HConstant>(static_cast<int32_t>( | 2166 unaligned_size, Add<HConstant>(static_cast<int32_t>( |
2167 header_size + kObjectAlignmentMask))); | 2167 header_size + kObjectAlignmentMask))); |
2168 size->ClearFlag(HValue::kCanOverflow); | 2168 size->ClearFlag(HValue::kCanOverflow); |
2169 return AddUncasted<HBitwise>( | 2169 return AddUncasted<HBitwise>( |
2170 Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>( | 2170 Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>( |
2171 ~kObjectAlignmentMask))); | 2171 ~kObjectAlignmentMask))); |
2172 } | 2172 } |
2173 | 2173 |
2174 | 2174 |
2175 HValue* HGraphBuilder::BuildUncheckedStringAdd( | 2175 HValue* HGraphBuilder::BuildUncheckedStringAdd( |
2176 HValue* left, | 2176 HValue* left, |
2177 HValue* right, | 2177 HValue* right, |
2178 HAllocationMode allocation_mode) { | 2178 HAllocationMode allocation_mode) { |
2179 // Determine the string lengths. | 2179 // Determine the string lengths. |
2180 HValue* left_length = AddLoadStringLength(left); | 2180 HValue* left_length = AddLoadStringLength(left); |
2181 HValue* right_length = AddLoadStringLength(right); | 2181 HValue* right_length = AddLoadStringLength(right); |
2182 | 2182 |
2183 // Compute the combined string length. | 2183 // Compute the combined string length. |
2184 HValue* length = BuildAddStringLengths(left_length, right_length); | 2184 HValue* length = BuildAddStringLengths(left_length, right_length); |
2185 | 2185 |
2186 // Do some manual constant folding here. | 2186 // Do some manual constant folding here. |
2187 if (left_length->IsConstant()) { | 2187 if (left_length->IsConstant()) { |
2188 HConstant* c_left_length = HConstant::cast(left_length); | 2188 HConstant* c_left_length = HConstant::cast(left_length); |
2189 ASSERT_NE(0, c_left_length->Integer32Value()); | 2189 DCHECK_NE(0, c_left_length->Integer32Value()); |
2190 if (c_left_length->Integer32Value() + 1 >= ConsString::kMinLength) { | 2190 if (c_left_length->Integer32Value() + 1 >= ConsString::kMinLength) { |
2191 // The right string contains at least one character. | 2191 // The right string contains at least one character. |
2192 return BuildCreateConsString(length, left, right, allocation_mode); | 2192 return BuildCreateConsString(length, left, right, allocation_mode); |
2193 } | 2193 } |
2194 } else if (right_length->IsConstant()) { | 2194 } else if (right_length->IsConstant()) { |
2195 HConstant* c_right_length = HConstant::cast(right_length); | 2195 HConstant* c_right_length = HConstant::cast(right_length); |
2196 ASSERT_NE(0, c_right_length->Integer32Value()); | 2196 DCHECK_NE(0, c_right_length->Integer32Value()); |
2197 if (c_right_length->Integer32Value() + 1 >= ConsString::kMinLength) { | 2197 if (c_right_length->Integer32Value() + 1 >= ConsString::kMinLength) { |
2198 // The left string contains at least one character. | 2198 // The left string contains at least one character. |
2199 return BuildCreateConsString(length, left, right, allocation_mode); | 2199 return BuildCreateConsString(length, left, right, allocation_mode); |
2200 } | 2200 } |
2201 } | 2201 } |
2202 | 2202 |
2203 // Check if we should create a cons string. | 2203 // Check if we should create a cons string. |
2204 IfBuilder if_createcons(this); | 2204 IfBuilder if_createcons(this); |
2205 if_createcons.If<HCompareNumericAndBranch>( | 2205 if_createcons.If<HCompareNumericAndBranch>( |
2206 length, Add<HConstant>(ConsString::kMinLength), Token::GTE); | 2206 length, Add<HConstant>(ConsString::kMinLength), Token::GTE); |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2392 | 2392 |
2393 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | 2393 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
2394 HValue* checked_object, | 2394 HValue* checked_object, |
2395 HValue* key, | 2395 HValue* key, |
2396 HValue* val, | 2396 HValue* val, |
2397 bool is_js_array, | 2397 bool is_js_array, |
2398 ElementsKind elements_kind, | 2398 ElementsKind elements_kind, |
2399 PropertyAccessType access_type, | 2399 PropertyAccessType access_type, |
2400 LoadKeyedHoleMode load_mode, | 2400 LoadKeyedHoleMode load_mode, |
2401 KeyedAccessStoreMode store_mode) { | 2401 KeyedAccessStoreMode store_mode) { |
2402 ASSERT((!IsExternalArrayElementsKind(elements_kind) && | 2402 DCHECK((!IsExternalArrayElementsKind(elements_kind) && |
2403 !IsFixedTypedArrayElementsKind(elements_kind)) || | 2403 !IsFixedTypedArrayElementsKind(elements_kind)) || |
2404 !is_js_array); | 2404 !is_js_array); |
2405 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency | 2405 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency |
2406 // on a HElementsTransition instruction. The flag can also be removed if the | 2406 // on a HElementsTransition instruction. The flag can also be removed if the |
2407 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further | 2407 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further |
2408 // ElementsKind transitions. Finally, the dependency can be removed for stores | 2408 // ElementsKind transitions. Finally, the dependency can be removed for stores |
2409 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the | 2409 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the |
2410 // generated store code. | 2410 // generated store code. |
2411 if ((elements_kind == FAST_HOLEY_ELEMENTS) || | 2411 if ((elements_kind == FAST_HOLEY_ELEMENTS) || |
2412 (elements_kind == FAST_ELEMENTS && access_type == STORE)) { | 2412 (elements_kind == FAST_ELEMENTS && access_type == STORE)) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2451 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( | 2451 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( |
2452 key, graph()->GetConstant0(), Token::GTE); | 2452 key, graph()->GetConstant0(), Token::GTE); |
2453 negative_checker.Then(); | 2453 negative_checker.Then(); |
2454 HInstruction* result = AddElementAccess( | 2454 HInstruction* result = AddElementAccess( |
2455 backing_store, key, val, bounds_check, elements_kind, access_type); | 2455 backing_store, key, val, bounds_check, elements_kind, access_type); |
2456 negative_checker.ElseDeopt("Negative key encountered"); | 2456 negative_checker.ElseDeopt("Negative key encountered"); |
2457 negative_checker.End(); | 2457 negative_checker.End(); |
2458 length_checker.End(); | 2458 length_checker.End(); |
2459 return result; | 2459 return result; |
2460 } else { | 2460 } else { |
2461 ASSERT(store_mode == STANDARD_STORE); | 2461 DCHECK(store_mode == STANDARD_STORE); |
2462 checked_key = Add<HBoundsCheck>(key, length); | 2462 checked_key = Add<HBoundsCheck>(key, length); |
2463 return AddElementAccess( | 2463 return AddElementAccess( |
2464 backing_store, checked_key, val, | 2464 backing_store, checked_key, val, |
2465 checked_object, elements_kind, access_type); | 2465 checked_object, elements_kind, access_type); |
2466 } | 2466 } |
2467 } | 2467 } |
2468 ASSERT(fast_smi_only_elements || | 2468 DCHECK(fast_smi_only_elements || |
2469 fast_elements || | 2469 fast_elements || |
2470 IsFastDoubleElementsKind(elements_kind)); | 2470 IsFastDoubleElementsKind(elements_kind)); |
2471 | 2471 |
2472 // In case val is stored into a fast smi array, assure that the value is a smi | 2472 // In case val is stored into a fast smi array, assure that the value is a smi |
2473 // before manipulating the backing store. Otherwise the actual store may | 2473 // before manipulating the backing store. Otherwise the actual store may |
2474 // deopt, leaving the backing store in an invalid state. | 2474 // deopt, leaving the backing store in an invalid state. |
2475 if (access_type == STORE && IsFastSmiElementsKind(elements_kind) && | 2475 if (access_type == STORE && IsFastSmiElementsKind(elements_kind) && |
2476 !val->type().IsSmi()) { | 2476 !val->type().IsSmi()) { |
2477 val = AddUncasted<HForceRepresentation>(val, Representation::Smi()); | 2477 val = AddUncasted<HForceRepresentation>(val, Representation::Smi()); |
2478 } | 2478 } |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2665 | 2665 |
2666 HInstruction* HGraphBuilder::AddElementAccess( | 2666 HInstruction* HGraphBuilder::AddElementAccess( |
2667 HValue* elements, | 2667 HValue* elements, |
2668 HValue* checked_key, | 2668 HValue* checked_key, |
2669 HValue* val, | 2669 HValue* val, |
2670 HValue* dependency, | 2670 HValue* dependency, |
2671 ElementsKind elements_kind, | 2671 ElementsKind elements_kind, |
2672 PropertyAccessType access_type, | 2672 PropertyAccessType access_type, |
2673 LoadKeyedHoleMode load_mode) { | 2673 LoadKeyedHoleMode load_mode) { |
2674 if (access_type == STORE) { | 2674 if (access_type == STORE) { |
2675 ASSERT(val != NULL); | 2675 DCHECK(val != NULL); |
2676 if (elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS || | 2676 if (elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS || |
2677 elements_kind == UINT8_CLAMPED_ELEMENTS) { | 2677 elements_kind == UINT8_CLAMPED_ELEMENTS) { |
2678 val = Add<HClampToUint8>(val); | 2678 val = Add<HClampToUint8>(val); |
2679 } | 2679 } |
2680 return Add<HStoreKeyed>(elements, checked_key, val, elements_kind, | 2680 return Add<HStoreKeyed>(elements, checked_key, val, elements_kind, |
2681 STORE_TO_INITIALIZED_ENTRY); | 2681 STORE_TO_INITIALIZED_ENTRY); |
2682 } | 2682 } |
2683 | 2683 |
2684 ASSERT(access_type == LOAD); | 2684 DCHECK(access_type == LOAD); |
2685 ASSERT(val == NULL); | 2685 DCHECK(val == NULL); |
2686 HLoadKeyed* load = Add<HLoadKeyed>( | 2686 HLoadKeyed* load = Add<HLoadKeyed>( |
2687 elements, checked_key, dependency, elements_kind, load_mode); | 2687 elements, checked_key, dependency, elements_kind, load_mode); |
2688 if (FLAG_opt_safe_uint32_operations && | 2688 if (FLAG_opt_safe_uint32_operations && |
2689 (elements_kind == EXTERNAL_UINT32_ELEMENTS || | 2689 (elements_kind == EXTERNAL_UINT32_ELEMENTS || |
2690 elements_kind == UINT32_ELEMENTS)) { | 2690 elements_kind == UINT32_ELEMENTS)) { |
2691 graph()->RecordUint32Instruction(load); | 2691 graph()->RecordUint32Instruction(load); |
2692 } | 2692 } |
2693 return load; | 2693 return load; |
2694 } | 2694 } |
2695 | 2695 |
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3064 } | 3064 } |
3065 | 3065 |
3066 if_nil.CaptureContinuation(continuation); | 3066 if_nil.CaptureContinuation(continuation); |
3067 } | 3067 } |
3068 | 3068 |
3069 | 3069 |
3070 void HGraphBuilder::BuildCreateAllocationMemento( | 3070 void HGraphBuilder::BuildCreateAllocationMemento( |
3071 HValue* previous_object, | 3071 HValue* previous_object, |
3072 HValue* previous_object_size, | 3072 HValue* previous_object_size, |
3073 HValue* allocation_site) { | 3073 HValue* allocation_site) { |
3074 ASSERT(allocation_site != NULL); | 3074 DCHECK(allocation_site != NULL); |
3075 HInnerAllocatedObject* allocation_memento = Add<HInnerAllocatedObject>( | 3075 HInnerAllocatedObject* allocation_memento = Add<HInnerAllocatedObject>( |
3076 previous_object, previous_object_size, HType::HeapObject()); | 3076 previous_object, previous_object_size, HType::HeapObject()); |
3077 AddStoreMapConstant( | 3077 AddStoreMapConstant( |
3078 allocation_memento, isolate()->factory()->allocation_memento_map()); | 3078 allocation_memento, isolate()->factory()->allocation_memento_map()); |
3079 Add<HStoreNamedField>( | 3079 Add<HStoreNamedField>( |
3080 allocation_memento, | 3080 allocation_memento, |
3081 HObjectAccess::ForAllocationMementoSite(), | 3081 HObjectAccess::ForAllocationMementoSite(), |
3082 allocation_site); | 3082 allocation_site); |
3083 if (FLAG_allocation_site_pretenuring) { | 3083 if (FLAG_allocation_site_pretenuring) { |
3084 HValue* memento_create_count = Add<HLoadNamedField>( | 3084 HValue* memento_create_count = Add<HLoadNamedField>( |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3135 | 3135 |
3136 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, | 3136 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, |
3137 ElementsKind kind, | 3137 ElementsKind kind, |
3138 HValue* allocation_site_payload, | 3138 HValue* allocation_site_payload, |
3139 HValue* constructor_function, | 3139 HValue* constructor_function, |
3140 AllocationSiteOverrideMode override_mode) : | 3140 AllocationSiteOverrideMode override_mode) : |
3141 builder_(builder), | 3141 builder_(builder), |
3142 kind_(kind), | 3142 kind_(kind), |
3143 allocation_site_payload_(allocation_site_payload), | 3143 allocation_site_payload_(allocation_site_payload), |
3144 constructor_function_(constructor_function) { | 3144 constructor_function_(constructor_function) { |
3145 ASSERT(!allocation_site_payload->IsConstant() || | 3145 DCHECK(!allocation_site_payload->IsConstant() || |
3146 HConstant::cast(allocation_site_payload)->handle( | 3146 HConstant::cast(allocation_site_payload)->handle( |
3147 builder_->isolate())->IsAllocationSite()); | 3147 builder_->isolate())->IsAllocationSite()); |
3148 mode_ = override_mode == DISABLE_ALLOCATION_SITES | 3148 mode_ = override_mode == DISABLE_ALLOCATION_SITES |
3149 ? DONT_TRACK_ALLOCATION_SITE | 3149 ? DONT_TRACK_ALLOCATION_SITE |
3150 : AllocationSite::GetMode(kind); | 3150 : AllocationSite::GetMode(kind); |
3151 } | 3151 } |
3152 | 3152 |
3153 | 3153 |
3154 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, | 3154 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, |
3155 ElementsKind kind, | 3155 ElementsKind kind, |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3447 | 3447 |
3448 HBasicBlock* HGraph::CreateBasicBlock() { | 3448 HBasicBlock* HGraph::CreateBasicBlock() { |
3449 HBasicBlock* result = new(zone()) HBasicBlock(this); | 3449 HBasicBlock* result = new(zone()) HBasicBlock(this); |
3450 blocks_.Add(result, zone()); | 3450 blocks_.Add(result, zone()); |
3451 return result; | 3451 return result; |
3452 } | 3452 } |
3453 | 3453 |
3454 | 3454 |
3455 void HGraph::FinalizeUniqueness() { | 3455 void HGraph::FinalizeUniqueness() { |
3456 DisallowHeapAllocation no_gc; | 3456 DisallowHeapAllocation no_gc; |
3457 ASSERT(!OptimizingCompilerThread::IsOptimizerThread(isolate())); | 3457 DCHECK(!OptimizingCompilerThread::IsOptimizerThread(isolate())); |
3458 for (int i = 0; i < blocks()->length(); ++i) { | 3458 for (int i = 0; i < blocks()->length(); ++i) { |
3459 for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) { | 3459 for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) { |
3460 it.Current()->FinalizeUniqueness(); | 3460 it.Current()->FinalizeUniqueness(); |
3461 } | 3461 } |
3462 } | 3462 } |
3463 } | 3463 } |
3464 | 3464 |
3465 | 3465 |
3466 int HGraph::TraceInlinedFunction( | 3466 int HGraph::TraceInlinedFunction( |
3467 Handle<SharedFunctionInfo> shared, | 3467 Handle<SharedFunctionInfo> shared, |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3634 block->MarkAsOrdered(); | 3634 block->MarkAsOrdered(); |
3635 | 3635 |
3636 if (block->IsLoopHeader()) { | 3636 if (block->IsLoopHeader()) { |
3637 kind_ = SUCCESSORS_OF_LOOP_HEADER; | 3637 kind_ = SUCCESSORS_OF_LOOP_HEADER; |
3638 loop_header_ = block; | 3638 loop_header_ = block; |
3639 InitializeSuccessors(); | 3639 InitializeSuccessors(); |
3640 PostorderProcessor* result = Push(zone); | 3640 PostorderProcessor* result = Push(zone); |
3641 return result->SetupLoopMembers(zone, block, block->loop_information(), | 3641 return result->SetupLoopMembers(zone, block, block->loop_information(), |
3642 loop_header); | 3642 loop_header); |
3643 } else { | 3643 } else { |
3644 ASSERT(block->IsFinished()); | 3644 DCHECK(block->IsFinished()); |
3645 kind_ = SUCCESSORS; | 3645 kind_ = SUCCESSORS; |
3646 loop_header_ = loop_header; | 3646 loop_header_ = loop_header; |
3647 InitializeSuccessors(); | 3647 InitializeSuccessors(); |
3648 return this; | 3648 return this; |
3649 } | 3649 } |
3650 } | 3650 } |
3651 } | 3651 } |
3652 | 3652 |
3653 PostorderProcessor* SetupLoopMembers(Zone* zone, | 3653 PostorderProcessor* SetupLoopMembers(Zone* zone, |
3654 HBasicBlock* block, | 3654 HBasicBlock* block, |
(...skipping 21 matching lines...) Expand all Loading... |
3676 | 3676 |
3677 // This method "allocates" a new stack frame. | 3677 // This method "allocates" a new stack frame. |
3678 PostorderProcessor* Push(Zone* zone) { | 3678 PostorderProcessor* Push(Zone* zone) { |
3679 if (child_ == NULL) { | 3679 if (child_ == NULL) { |
3680 child_ = new(zone) PostorderProcessor(this); | 3680 child_ = new(zone) PostorderProcessor(this); |
3681 } | 3681 } |
3682 return child_; | 3682 return child_; |
3683 } | 3683 } |
3684 | 3684 |
3685 void ClosePostorder(ZoneList<HBasicBlock*>* order, Zone* zone) { | 3685 void ClosePostorder(ZoneList<HBasicBlock*>* order, Zone* zone) { |
3686 ASSERT(block_->end()->FirstSuccessor() == NULL || | 3686 DCHECK(block_->end()->FirstSuccessor() == NULL || |
3687 order->Contains(block_->end()->FirstSuccessor()) || | 3687 order->Contains(block_->end()->FirstSuccessor()) || |
3688 block_->end()->FirstSuccessor()->IsLoopHeader()); | 3688 block_->end()->FirstSuccessor()->IsLoopHeader()); |
3689 ASSERT(block_->end()->SecondSuccessor() == NULL || | 3689 DCHECK(block_->end()->SecondSuccessor() == NULL || |
3690 order->Contains(block_->end()->SecondSuccessor()) || | 3690 order->Contains(block_->end()->SecondSuccessor()) || |
3691 block_->end()->SecondSuccessor()->IsLoopHeader()); | 3691 block_->end()->SecondSuccessor()->IsLoopHeader()); |
3692 order->Add(block_, zone); | 3692 order->Add(block_, zone); |
3693 } | 3693 } |
3694 | 3694 |
3695 // This method is the basic block to walk up the stack. | 3695 // This method is the basic block to walk up the stack. |
3696 PostorderProcessor* Pop(Zone* zone, | 3696 PostorderProcessor* Pop(Zone* zone, |
3697 ZoneList<HBasicBlock*>* order) { | 3697 ZoneList<HBasicBlock*>* order) { |
3698 switch (kind_) { | 3698 switch (kind_) { |
3699 case SUCCESSORS: | 3699 case SUCCESSORS: |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3817 HSuccessorIterator successor_iterator; | 3817 HSuccessorIterator successor_iterator; |
3818 }; | 3818 }; |
3819 | 3819 |
3820 | 3820 |
3821 void HGraph::OrderBlocks() { | 3821 void HGraph::OrderBlocks() { |
3822 CompilationPhase phase("H_Block ordering", info()); | 3822 CompilationPhase phase("H_Block ordering", info()); |
3823 | 3823 |
3824 #ifdef DEBUG | 3824 #ifdef DEBUG |
3825 // Initially the blocks must not be ordered. | 3825 // Initially the blocks must not be ordered. |
3826 for (int i = 0; i < blocks_.length(); ++i) { | 3826 for (int i = 0; i < blocks_.length(); ++i) { |
3827 ASSERT(!blocks_[i]->IsOrdered()); | 3827 DCHECK(!blocks_[i]->IsOrdered()); |
3828 } | 3828 } |
3829 #endif | 3829 #endif |
3830 | 3830 |
3831 PostorderProcessor* postorder = | 3831 PostorderProcessor* postorder = |
3832 PostorderProcessor::CreateEntryProcessor(zone(), blocks_[0]); | 3832 PostorderProcessor::CreateEntryProcessor(zone(), blocks_[0]); |
3833 blocks_.Rewind(0); | 3833 blocks_.Rewind(0); |
3834 while (postorder) { | 3834 while (postorder) { |
3835 postorder = postorder->PerformStep(zone(), &blocks_); | 3835 postorder = postorder->PerformStep(zone(), &blocks_); |
3836 } | 3836 } |
3837 | 3837 |
3838 #ifdef DEBUG | 3838 #ifdef DEBUG |
3839 // Now all blocks must be marked as ordered. | 3839 // Now all blocks must be marked as ordered. |
3840 for (int i = 0; i < blocks_.length(); ++i) { | 3840 for (int i = 0; i < blocks_.length(); ++i) { |
3841 ASSERT(blocks_[i]->IsOrdered()); | 3841 DCHECK(blocks_[i]->IsOrdered()); |
3842 } | 3842 } |
3843 #endif | 3843 #endif |
3844 | 3844 |
3845 // Reverse block list and assign block IDs. | 3845 // Reverse block list and assign block IDs. |
3846 for (int i = 0, j = blocks_.length(); --j >= i; ++i) { | 3846 for (int i = 0, j = blocks_.length(); --j >= i; ++i) { |
3847 HBasicBlock* bi = blocks_[i]; | 3847 HBasicBlock* bi = blocks_[i]; |
3848 HBasicBlock* bj = blocks_[j]; | 3848 HBasicBlock* bj = blocks_[j]; |
3849 bi->set_block_id(j); | 3849 bi->set_block_id(j); |
3850 bj->set_block_id(i); | 3850 bj->set_block_id(i); |
3851 blocks_[i] = bj; | 3851 blocks_[i] = bj; |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3978 | 3978 |
3979 // Implementation of utility classes to represent an expression's context in | 3979 // Implementation of utility classes to represent an expression's context in |
3980 // the AST. | 3980 // the AST. |
3981 AstContext::AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind) | 3981 AstContext::AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind) |
3982 : owner_(owner), | 3982 : owner_(owner), |
3983 kind_(kind), | 3983 kind_(kind), |
3984 outer_(owner->ast_context()), | 3984 outer_(owner->ast_context()), |
3985 for_typeof_(false) { | 3985 for_typeof_(false) { |
3986 owner->set_ast_context(this); // Push. | 3986 owner->set_ast_context(this); // Push. |
3987 #ifdef DEBUG | 3987 #ifdef DEBUG |
3988 ASSERT(owner->environment()->frame_type() == JS_FUNCTION); | 3988 DCHECK(owner->environment()->frame_type() == JS_FUNCTION); |
3989 original_length_ = owner->environment()->length(); | 3989 original_length_ = owner->environment()->length(); |
3990 #endif | 3990 #endif |
3991 } | 3991 } |
3992 | 3992 |
3993 | 3993 |
3994 AstContext::~AstContext() { | 3994 AstContext::~AstContext() { |
3995 owner_->set_ast_context(outer_); // Pop. | 3995 owner_->set_ast_context(outer_); // Pop. |
3996 } | 3996 } |
3997 | 3997 |
3998 | 3998 |
3999 EffectContext::~EffectContext() { | 3999 EffectContext::~EffectContext() { |
4000 ASSERT(owner()->HasStackOverflow() || | 4000 DCHECK(owner()->HasStackOverflow() || |
4001 owner()->current_block() == NULL || | 4001 owner()->current_block() == NULL || |
4002 (owner()->environment()->length() == original_length_ && | 4002 (owner()->environment()->length() == original_length_ && |
4003 owner()->environment()->frame_type() == JS_FUNCTION)); | 4003 owner()->environment()->frame_type() == JS_FUNCTION)); |
4004 } | 4004 } |
4005 | 4005 |
4006 | 4006 |
4007 ValueContext::~ValueContext() { | 4007 ValueContext::~ValueContext() { |
4008 ASSERT(owner()->HasStackOverflow() || | 4008 DCHECK(owner()->HasStackOverflow() || |
4009 owner()->current_block() == NULL || | 4009 owner()->current_block() == NULL || |
4010 (owner()->environment()->length() == original_length_ + 1 && | 4010 (owner()->environment()->length() == original_length_ + 1 && |
4011 owner()->environment()->frame_type() == JS_FUNCTION)); | 4011 owner()->environment()->frame_type() == JS_FUNCTION)); |
4012 } | 4012 } |
4013 | 4013 |
4014 | 4014 |
4015 void EffectContext::ReturnValue(HValue* value) { | 4015 void EffectContext::ReturnValue(HValue* value) { |
4016 // The value is simply ignored. | 4016 // The value is simply ignored. |
4017 } | 4017 } |
4018 | 4018 |
4019 | 4019 |
4020 void ValueContext::ReturnValue(HValue* value) { | 4020 void ValueContext::ReturnValue(HValue* value) { |
4021 // The value is tracked in the bailout environment, and communicated | 4021 // The value is tracked in the bailout environment, and communicated |
4022 // through the environment as the result of the expression. | 4022 // through the environment as the result of the expression. |
4023 if (!arguments_allowed() && value->CheckFlag(HValue::kIsArguments)) { | 4023 if (!arguments_allowed() && value->CheckFlag(HValue::kIsArguments)) { |
4024 owner()->Bailout(kBadValueContextForArgumentsValue); | 4024 owner()->Bailout(kBadValueContextForArgumentsValue); |
4025 } | 4025 } |
4026 owner()->Push(value); | 4026 owner()->Push(value); |
4027 } | 4027 } |
4028 | 4028 |
4029 | 4029 |
4030 void TestContext::ReturnValue(HValue* value) { | 4030 void TestContext::ReturnValue(HValue* value) { |
4031 BuildBranch(value); | 4031 BuildBranch(value); |
4032 } | 4032 } |
4033 | 4033 |
4034 | 4034 |
4035 void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 4035 void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
4036 ASSERT(!instr->IsControlInstruction()); | 4036 DCHECK(!instr->IsControlInstruction()); |
4037 owner()->AddInstruction(instr); | 4037 owner()->AddInstruction(instr); |
4038 if (instr->HasObservableSideEffects()) { | 4038 if (instr->HasObservableSideEffects()) { |
4039 owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 4039 owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
4040 } | 4040 } |
4041 } | 4041 } |
4042 | 4042 |
4043 | 4043 |
4044 void EffectContext::ReturnControl(HControlInstruction* instr, | 4044 void EffectContext::ReturnControl(HControlInstruction* instr, |
4045 BailoutId ast_id) { | 4045 BailoutId ast_id) { |
4046 ASSERT(!instr->HasObservableSideEffects()); | 4046 DCHECK(!instr->HasObservableSideEffects()); |
4047 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); | 4047 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); |
4048 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); | 4048 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
4049 instr->SetSuccessorAt(0, empty_true); | 4049 instr->SetSuccessorAt(0, empty_true); |
4050 instr->SetSuccessorAt(1, empty_false); | 4050 instr->SetSuccessorAt(1, empty_false); |
4051 owner()->FinishCurrentBlock(instr); | 4051 owner()->FinishCurrentBlock(instr); |
4052 HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id); | 4052 HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id); |
4053 owner()->set_current_block(join); | 4053 owner()->set_current_block(join); |
4054 } | 4054 } |
4055 | 4055 |
4056 | 4056 |
4057 void EffectContext::ReturnContinuation(HIfContinuation* continuation, | 4057 void EffectContext::ReturnContinuation(HIfContinuation* continuation, |
4058 BailoutId ast_id) { | 4058 BailoutId ast_id) { |
4059 HBasicBlock* true_branch = NULL; | 4059 HBasicBlock* true_branch = NULL; |
4060 HBasicBlock* false_branch = NULL; | 4060 HBasicBlock* false_branch = NULL; |
4061 continuation->Continue(&true_branch, &false_branch); | 4061 continuation->Continue(&true_branch, &false_branch); |
4062 if (!continuation->IsTrueReachable()) { | 4062 if (!continuation->IsTrueReachable()) { |
4063 owner()->set_current_block(false_branch); | 4063 owner()->set_current_block(false_branch); |
4064 } else if (!continuation->IsFalseReachable()) { | 4064 } else if (!continuation->IsFalseReachable()) { |
4065 owner()->set_current_block(true_branch); | 4065 owner()->set_current_block(true_branch); |
4066 } else { | 4066 } else { |
4067 HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id); | 4067 HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id); |
4068 owner()->set_current_block(join); | 4068 owner()->set_current_block(join); |
4069 } | 4069 } |
4070 } | 4070 } |
4071 | 4071 |
4072 | 4072 |
4073 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 4073 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
4074 ASSERT(!instr->IsControlInstruction()); | 4074 DCHECK(!instr->IsControlInstruction()); |
4075 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { | 4075 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
4076 return owner()->Bailout(kBadValueContextForArgumentsObjectValue); | 4076 return owner()->Bailout(kBadValueContextForArgumentsObjectValue); |
4077 } | 4077 } |
4078 owner()->AddInstruction(instr); | 4078 owner()->AddInstruction(instr); |
4079 owner()->Push(instr); | 4079 owner()->Push(instr); |
4080 if (instr->HasObservableSideEffects()) { | 4080 if (instr->HasObservableSideEffects()) { |
4081 owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 4081 owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
4082 } | 4082 } |
4083 } | 4083 } |
4084 | 4084 |
4085 | 4085 |
4086 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { | 4086 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { |
4087 ASSERT(!instr->HasObservableSideEffects()); | 4087 DCHECK(!instr->HasObservableSideEffects()); |
4088 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { | 4088 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
4089 return owner()->Bailout(kBadValueContextForArgumentsObjectValue); | 4089 return owner()->Bailout(kBadValueContextForArgumentsObjectValue); |
4090 } | 4090 } |
4091 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); | 4091 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); |
4092 HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock(); | 4092 HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock(); |
4093 instr->SetSuccessorAt(0, materialize_true); | 4093 instr->SetSuccessorAt(0, materialize_true); |
4094 instr->SetSuccessorAt(1, materialize_false); | 4094 instr->SetSuccessorAt(1, materialize_false); |
4095 owner()->FinishCurrentBlock(instr); | 4095 owner()->FinishCurrentBlock(instr); |
4096 owner()->set_current_block(materialize_true); | 4096 owner()->set_current_block(materialize_true); |
4097 owner()->Push(owner()->graph()->GetConstantTrue()); | 4097 owner()->Push(owner()->graph()->GetConstantTrue()); |
(...skipping 22 matching lines...) Expand all Loading... |
4120 } | 4120 } |
4121 if (continuation->TrueAndFalseReachable()) { | 4121 if (continuation->TrueAndFalseReachable()) { |
4122 HBasicBlock* join = | 4122 HBasicBlock* join = |
4123 owner()->CreateJoin(materialize_true, materialize_false, ast_id); | 4123 owner()->CreateJoin(materialize_true, materialize_false, ast_id); |
4124 owner()->set_current_block(join); | 4124 owner()->set_current_block(join); |
4125 } | 4125 } |
4126 } | 4126 } |
4127 | 4127 |
4128 | 4128 |
4129 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 4129 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
4130 ASSERT(!instr->IsControlInstruction()); | 4130 DCHECK(!instr->IsControlInstruction()); |
4131 HOptimizedGraphBuilder* builder = owner(); | 4131 HOptimizedGraphBuilder* builder = owner(); |
4132 builder->AddInstruction(instr); | 4132 builder->AddInstruction(instr); |
4133 // We expect a simulate after every expression with side effects, though | 4133 // We expect a simulate after every expression with side effects, though |
4134 // this one isn't actually needed (and wouldn't work if it were targeted). | 4134 // this one isn't actually needed (and wouldn't work if it were targeted). |
4135 if (instr->HasObservableSideEffects()) { | 4135 if (instr->HasObservableSideEffects()) { |
4136 builder->Push(instr); | 4136 builder->Push(instr); |
4137 builder->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 4137 builder->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
4138 builder->Pop(); | 4138 builder->Pop(); |
4139 } | 4139 } |
4140 BuildBranch(instr); | 4140 BuildBranch(instr); |
4141 } | 4141 } |
4142 | 4142 |
4143 | 4143 |
4144 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { | 4144 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { |
4145 ASSERT(!instr->HasObservableSideEffects()); | 4145 DCHECK(!instr->HasObservableSideEffects()); |
4146 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); | 4146 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); |
4147 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); | 4147 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
4148 instr->SetSuccessorAt(0, empty_true); | 4148 instr->SetSuccessorAt(0, empty_true); |
4149 instr->SetSuccessorAt(1, empty_false); | 4149 instr->SetSuccessorAt(1, empty_false); |
4150 owner()->FinishCurrentBlock(instr); | 4150 owner()->FinishCurrentBlock(instr); |
4151 owner()->Goto(empty_true, if_true(), owner()->function_state()); | 4151 owner()->Goto(empty_true, if_true(), owner()->function_state()); |
4152 owner()->Goto(empty_false, if_false(), owner()->function_state()); | 4152 owner()->Goto(empty_false, if_false(), owner()->function_state()); |
4153 owner()->set_current_block(NULL); | 4153 owner()->set_current_block(NULL); |
4154 } | 4154 } |
4155 | 4155 |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4300 if (current_block() != NULL) { | 4300 if (current_block() != NULL) { |
4301 Add<HReturn>(graph()->GetConstantUndefined()); | 4301 Add<HReturn>(graph()->GetConstantUndefined()); |
4302 set_current_block(NULL); | 4302 set_current_block(NULL); |
4303 } | 4303 } |
4304 | 4304 |
4305 // If the checksum of the number of type info changes is the same as the | 4305 // If the checksum of the number of type info changes is the same as the |
4306 // last time this function was compiled, then this recompile is likely not | 4306 // last time this function was compiled, then this recompile is likely not |
4307 // due to missing/inadequate type feedback, but rather too aggressive | 4307 // due to missing/inadequate type feedback, but rather too aggressive |
4308 // optimization. Disable optimistic LICM in that case. | 4308 // optimization. Disable optimistic LICM in that case. |
4309 Handle<Code> unoptimized_code(current_info()->shared_info()->code()); | 4309 Handle<Code> unoptimized_code(current_info()->shared_info()->code()); |
4310 ASSERT(unoptimized_code->kind() == Code::FUNCTION); | 4310 DCHECK(unoptimized_code->kind() == Code::FUNCTION); |
4311 Handle<TypeFeedbackInfo> type_info( | 4311 Handle<TypeFeedbackInfo> type_info( |
4312 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); | 4312 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); |
4313 int checksum = type_info->own_type_change_checksum(); | 4313 int checksum = type_info->own_type_change_checksum(); |
4314 int composite_checksum = graph()->update_type_change_checksum(checksum); | 4314 int composite_checksum = graph()->update_type_change_checksum(checksum); |
4315 graph()->set_use_optimistic_licm( | 4315 graph()->set_use_optimistic_licm( |
4316 !type_info->matches_inlined_type_change_checksum(composite_checksum)); | 4316 !type_info->matches_inlined_type_change_checksum(composite_checksum)); |
4317 type_info->set_inlined_type_change_checksum(composite_checksum); | 4317 type_info->set_inlined_type_change_checksum(composite_checksum); |
4318 | 4318 |
4319 // Perform any necessary OSR-specific cleanups or changes to the graph. | 4319 // Perform any necessary OSR-specific cleanups or changes to the graph. |
4320 osr()->FinishGraph(); | 4320 osr()->FinishGraph(); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4414 | 4414 |
4415 void HGraph::RestoreActualValues() { | 4415 void HGraph::RestoreActualValues() { |
4416 HPhase phase("H_Restore actual values", this); | 4416 HPhase phase("H_Restore actual values", this); |
4417 | 4417 |
4418 for (int block_index = 0; block_index < blocks()->length(); block_index++) { | 4418 for (int block_index = 0; block_index < blocks()->length(); block_index++) { |
4419 HBasicBlock* block = blocks()->at(block_index); | 4419 HBasicBlock* block = blocks()->at(block_index); |
4420 | 4420 |
4421 #ifdef DEBUG | 4421 #ifdef DEBUG |
4422 for (int i = 0; i < block->phis()->length(); i++) { | 4422 for (int i = 0; i < block->phis()->length(); i++) { |
4423 HPhi* phi = block->phis()->at(i); | 4423 HPhi* phi = block->phis()->at(i); |
4424 ASSERT(phi->ActualValue() == phi); | 4424 DCHECK(phi->ActualValue() == phi); |
4425 } | 4425 } |
4426 #endif | 4426 #endif |
4427 | 4427 |
4428 for (HInstructionIterator it(block); !it.Done(); it.Advance()) { | 4428 for (HInstructionIterator it(block); !it.Done(); it.Advance()) { |
4429 HInstruction* instruction = it.Current(); | 4429 HInstruction* instruction = it.Current(); |
4430 if (instruction->ActualValue() == instruction) continue; | 4430 if (instruction->ActualValue() == instruction) continue; |
4431 if (instruction->CheckFlag(HValue::kIsDead)) { | 4431 if (instruction->CheckFlag(HValue::kIsDead)) { |
4432 // The instruction was marked as deleted but left in the graph | 4432 // The instruction was marked as deleted but left in the graph |
4433 // as a control flow dependency point for subsequent | 4433 // as a control flow dependency point for subsequent |
4434 // instructions. | 4434 // instructions. |
4435 instruction->DeleteAndReplaceWith(instruction->ActualValue()); | 4435 instruction->DeleteAndReplaceWith(instruction->ActualValue()); |
4436 } else { | 4436 } else { |
4437 ASSERT(instruction->IsInformativeDefinition()); | 4437 DCHECK(instruction->IsInformativeDefinition()); |
4438 if (instruction->IsPurelyInformativeDefinition()) { | 4438 if (instruction->IsPurelyInformativeDefinition()) { |
4439 instruction->DeleteAndReplaceWith(instruction->RedefinedOperand()); | 4439 instruction->DeleteAndReplaceWith(instruction->RedefinedOperand()); |
4440 } else { | 4440 } else { |
4441 instruction->ReplaceAllUsesWith(instruction->ActualValue()); | 4441 instruction->ReplaceAllUsesWith(instruction->ActualValue()); |
4442 } | 4442 } |
4443 } | 4443 } |
4444 } | 4444 } |
4445 } | 4445 } |
4446 } | 4446 } |
4447 | 4447 |
(...skipping 19 matching lines...) Expand all Loading... |
4467 } | 4467 } |
4468 | 4468 |
4469 | 4469 |
4470 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) { | 4470 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) { |
4471 // First special is HContext. | 4471 // First special is HContext. |
4472 HInstruction* context = Add<HContext>(); | 4472 HInstruction* context = Add<HContext>(); |
4473 environment()->BindContext(context); | 4473 environment()->BindContext(context); |
4474 | 4474 |
4475 // Create an arguments object containing the initial parameters. Set the | 4475 // Create an arguments object containing the initial parameters. Set the |
4476 // initial values of parameters including "this" having parameter index 0. | 4476 // initial values of parameters including "this" having parameter index 0. |
4477 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count()); | 4477 DCHECK_EQ(scope->num_parameters() + 1, environment()->parameter_count()); |
4478 HArgumentsObject* arguments_object = | 4478 HArgumentsObject* arguments_object = |
4479 New<HArgumentsObject>(environment()->parameter_count()); | 4479 New<HArgumentsObject>(environment()->parameter_count()); |
4480 for (int i = 0; i < environment()->parameter_count(); ++i) { | 4480 for (int i = 0; i < environment()->parameter_count(); ++i) { |
4481 HInstruction* parameter = Add<HParameter>(i); | 4481 HInstruction* parameter = Add<HParameter>(i); |
4482 arguments_object->AddArgument(parameter, zone()); | 4482 arguments_object->AddArgument(parameter, zone()); |
4483 environment()->Bind(i, parameter); | 4483 environment()->Bind(i, parameter); |
4484 } | 4484 } |
4485 AddInstruction(arguments_object); | 4485 AddInstruction(arguments_object); |
4486 graph()->SetArgumentsObject(arguments_object); | 4486 graph()->SetArgumentsObject(arguments_object); |
4487 | 4487 |
(...skipping 21 matching lines...) Expand all Loading... |
4509 void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { | 4509 void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { |
4510 for (int i = 0; i < statements->length(); i++) { | 4510 for (int i = 0; i < statements->length(); i++) { |
4511 Statement* stmt = statements->at(i); | 4511 Statement* stmt = statements->at(i); |
4512 CHECK_ALIVE(Visit(stmt)); | 4512 CHECK_ALIVE(Visit(stmt)); |
4513 if (stmt->IsJump()) break; | 4513 if (stmt->IsJump()) break; |
4514 } | 4514 } |
4515 } | 4515 } |
4516 | 4516 |
4517 | 4517 |
4518 void HOptimizedGraphBuilder::VisitBlock(Block* stmt) { | 4518 void HOptimizedGraphBuilder::VisitBlock(Block* stmt) { |
4519 ASSERT(!HasStackOverflow()); | 4519 DCHECK(!HasStackOverflow()); |
4520 ASSERT(current_block() != NULL); | 4520 DCHECK(current_block() != NULL); |
4521 ASSERT(current_block()->HasPredecessor()); | 4521 DCHECK(current_block()->HasPredecessor()); |
4522 | 4522 |
4523 Scope* outer_scope = scope(); | 4523 Scope* outer_scope = scope(); |
4524 Scope* scope = stmt->scope(); | 4524 Scope* scope = stmt->scope(); |
4525 BreakAndContinueInfo break_info(stmt, outer_scope); | 4525 BreakAndContinueInfo break_info(stmt, outer_scope); |
4526 | 4526 |
4527 { BreakAndContinueScope push(&break_info, this); | 4527 { BreakAndContinueScope push(&break_info, this); |
4528 if (scope != NULL) { | 4528 if (scope != NULL) { |
4529 // Load the function object. | 4529 // Load the function object. |
4530 Scope* declaration_scope = scope->DeclarationScope(); | 4530 Scope* declaration_scope = scope->DeclarationScope(); |
4531 HInstruction* function; | 4531 HInstruction* function; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4569 if (break_block != NULL) { | 4569 if (break_block != NULL) { |
4570 if (current_block() != NULL) Goto(break_block); | 4570 if (current_block() != NULL) Goto(break_block); |
4571 break_block->SetJoinId(stmt->ExitId()); | 4571 break_block->SetJoinId(stmt->ExitId()); |
4572 set_current_block(break_block); | 4572 set_current_block(break_block); |
4573 } | 4573 } |
4574 } | 4574 } |
4575 | 4575 |
4576 | 4576 |
4577 void HOptimizedGraphBuilder::VisitExpressionStatement( | 4577 void HOptimizedGraphBuilder::VisitExpressionStatement( |
4578 ExpressionStatement* stmt) { | 4578 ExpressionStatement* stmt) { |
4579 ASSERT(!HasStackOverflow()); | 4579 DCHECK(!HasStackOverflow()); |
4580 ASSERT(current_block() != NULL); | 4580 DCHECK(current_block() != NULL); |
4581 ASSERT(current_block()->HasPredecessor()); | 4581 DCHECK(current_block()->HasPredecessor()); |
4582 VisitForEffect(stmt->expression()); | 4582 VisitForEffect(stmt->expression()); |
4583 } | 4583 } |
4584 | 4584 |
4585 | 4585 |
4586 void HOptimizedGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { | 4586 void HOptimizedGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { |
4587 ASSERT(!HasStackOverflow()); | 4587 DCHECK(!HasStackOverflow()); |
4588 ASSERT(current_block() != NULL); | 4588 DCHECK(current_block() != NULL); |
4589 ASSERT(current_block()->HasPredecessor()); | 4589 DCHECK(current_block()->HasPredecessor()); |
4590 } | 4590 } |
4591 | 4591 |
4592 | 4592 |
4593 void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) { | 4593 void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) { |
4594 ASSERT(!HasStackOverflow()); | 4594 DCHECK(!HasStackOverflow()); |
4595 ASSERT(current_block() != NULL); | 4595 DCHECK(current_block() != NULL); |
4596 ASSERT(current_block()->HasPredecessor()); | 4596 DCHECK(current_block()->HasPredecessor()); |
4597 if (stmt->condition()->ToBooleanIsTrue()) { | 4597 if (stmt->condition()->ToBooleanIsTrue()) { |
4598 Add<HSimulate>(stmt->ThenId()); | 4598 Add<HSimulate>(stmt->ThenId()); |
4599 Visit(stmt->then_statement()); | 4599 Visit(stmt->then_statement()); |
4600 } else if (stmt->condition()->ToBooleanIsFalse()) { | 4600 } else if (stmt->condition()->ToBooleanIsFalse()) { |
4601 Add<HSimulate>(stmt->ElseId()); | 4601 Add<HSimulate>(stmt->ElseId()); |
4602 Visit(stmt->else_statement()); | 4602 Visit(stmt->else_statement()); |
4603 } else { | 4603 } else { |
4604 HBasicBlock* cond_true = graph()->CreateBasicBlock(); | 4604 HBasicBlock* cond_true = graph()->CreateBasicBlock(); |
4605 HBasicBlock* cond_false = graph()->CreateBasicBlock(); | 4605 HBasicBlock* cond_false = graph()->CreateBasicBlock(); |
4606 CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false)); | 4606 CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false)); |
(...skipping 26 matching lines...) Expand all Loading... |
4633 BreakableStatement* stmt, | 4633 BreakableStatement* stmt, |
4634 BreakType type, | 4634 BreakType type, |
4635 Scope** scope, | 4635 Scope** scope, |
4636 int* drop_extra) { | 4636 int* drop_extra) { |
4637 *drop_extra = 0; | 4637 *drop_extra = 0; |
4638 BreakAndContinueScope* current = this; | 4638 BreakAndContinueScope* current = this; |
4639 while (current != NULL && current->info()->target() != stmt) { | 4639 while (current != NULL && current->info()->target() != stmt) { |
4640 *drop_extra += current->info()->drop_extra(); | 4640 *drop_extra += current->info()->drop_extra(); |
4641 current = current->next(); | 4641 current = current->next(); |
4642 } | 4642 } |
4643 ASSERT(current != NULL); // Always found (unless stack is malformed). | 4643 DCHECK(current != NULL); // Always found (unless stack is malformed). |
4644 *scope = current->info()->scope(); | 4644 *scope = current->info()->scope(); |
4645 | 4645 |
4646 if (type == BREAK) { | 4646 if (type == BREAK) { |
4647 *drop_extra += current->info()->drop_extra(); | 4647 *drop_extra += current->info()->drop_extra(); |
4648 } | 4648 } |
4649 | 4649 |
4650 HBasicBlock* block = NULL; | 4650 HBasicBlock* block = NULL; |
4651 switch (type) { | 4651 switch (type) { |
4652 case BREAK: | 4652 case BREAK: |
4653 block = current->info()->break_block(); | 4653 block = current->info()->break_block(); |
(...skipping 11 matching lines...) Expand all Loading... |
4665 } | 4665 } |
4666 break; | 4666 break; |
4667 } | 4667 } |
4668 | 4668 |
4669 return block; | 4669 return block; |
4670 } | 4670 } |
4671 | 4671 |
4672 | 4672 |
4673 void HOptimizedGraphBuilder::VisitContinueStatement( | 4673 void HOptimizedGraphBuilder::VisitContinueStatement( |
4674 ContinueStatement* stmt) { | 4674 ContinueStatement* stmt) { |
4675 ASSERT(!HasStackOverflow()); | 4675 DCHECK(!HasStackOverflow()); |
4676 ASSERT(current_block() != NULL); | 4676 DCHECK(current_block() != NULL); |
4677 ASSERT(current_block()->HasPredecessor()); | 4677 DCHECK(current_block()->HasPredecessor()); |
4678 Scope* outer_scope = NULL; | 4678 Scope* outer_scope = NULL; |
4679 Scope* inner_scope = scope(); | 4679 Scope* inner_scope = scope(); |
4680 int drop_extra = 0; | 4680 int drop_extra = 0; |
4681 HBasicBlock* continue_block = break_scope()->Get( | 4681 HBasicBlock* continue_block = break_scope()->Get( |
4682 stmt->target(), BreakAndContinueScope::CONTINUE, | 4682 stmt->target(), BreakAndContinueScope::CONTINUE, |
4683 &outer_scope, &drop_extra); | 4683 &outer_scope, &drop_extra); |
4684 HValue* context = environment()->context(); | 4684 HValue* context = environment()->context(); |
4685 Drop(drop_extra); | 4685 Drop(drop_extra); |
4686 int context_pop_count = inner_scope->ContextChainLength(outer_scope); | 4686 int context_pop_count = inner_scope->ContextChainLength(outer_scope); |
4687 if (context_pop_count > 0) { | 4687 if (context_pop_count > 0) { |
4688 while (context_pop_count-- > 0) { | 4688 while (context_pop_count-- > 0) { |
4689 HInstruction* context_instruction = Add<HLoadNamedField>( | 4689 HInstruction* context_instruction = Add<HLoadNamedField>( |
4690 context, static_cast<HValue*>(NULL), | 4690 context, static_cast<HValue*>(NULL), |
4691 HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX)); | 4691 HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX)); |
4692 context = context_instruction; | 4692 context = context_instruction; |
4693 } | 4693 } |
4694 HInstruction* instr = Add<HStoreFrameContext>(context); | 4694 HInstruction* instr = Add<HStoreFrameContext>(context); |
4695 if (instr->HasObservableSideEffects()) { | 4695 if (instr->HasObservableSideEffects()) { |
4696 AddSimulate(stmt->target()->EntryId(), REMOVABLE_SIMULATE); | 4696 AddSimulate(stmt->target()->EntryId(), REMOVABLE_SIMULATE); |
4697 } | 4697 } |
4698 environment()->BindContext(context); | 4698 environment()->BindContext(context); |
4699 } | 4699 } |
4700 | 4700 |
4701 Goto(continue_block); | 4701 Goto(continue_block); |
4702 set_current_block(NULL); | 4702 set_current_block(NULL); |
4703 } | 4703 } |
4704 | 4704 |
4705 | 4705 |
4706 void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { | 4706 void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { |
4707 ASSERT(!HasStackOverflow()); | 4707 DCHECK(!HasStackOverflow()); |
4708 ASSERT(current_block() != NULL); | 4708 DCHECK(current_block() != NULL); |
4709 ASSERT(current_block()->HasPredecessor()); | 4709 DCHECK(current_block()->HasPredecessor()); |
4710 Scope* outer_scope = NULL; | 4710 Scope* outer_scope = NULL; |
4711 Scope* inner_scope = scope(); | 4711 Scope* inner_scope = scope(); |
4712 int drop_extra = 0; | 4712 int drop_extra = 0; |
4713 HBasicBlock* break_block = break_scope()->Get( | 4713 HBasicBlock* break_block = break_scope()->Get( |
4714 stmt->target(), BreakAndContinueScope::BREAK, | 4714 stmt->target(), BreakAndContinueScope::BREAK, |
4715 &outer_scope, &drop_extra); | 4715 &outer_scope, &drop_extra); |
4716 HValue* context = environment()->context(); | 4716 HValue* context = environment()->context(); |
4717 Drop(drop_extra); | 4717 Drop(drop_extra); |
4718 int context_pop_count = inner_scope->ContextChainLength(outer_scope); | 4718 int context_pop_count = inner_scope->ContextChainLength(outer_scope); |
4719 if (context_pop_count > 0) { | 4719 if (context_pop_count > 0) { |
4720 while (context_pop_count-- > 0) { | 4720 while (context_pop_count-- > 0) { |
4721 HInstruction* context_instruction = Add<HLoadNamedField>( | 4721 HInstruction* context_instruction = Add<HLoadNamedField>( |
4722 context, static_cast<HValue*>(NULL), | 4722 context, static_cast<HValue*>(NULL), |
4723 HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX)); | 4723 HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX)); |
4724 context = context_instruction; | 4724 context = context_instruction; |
4725 } | 4725 } |
4726 HInstruction* instr = Add<HStoreFrameContext>(context); | 4726 HInstruction* instr = Add<HStoreFrameContext>(context); |
4727 if (instr->HasObservableSideEffects()) { | 4727 if (instr->HasObservableSideEffects()) { |
4728 AddSimulate(stmt->target()->ExitId(), REMOVABLE_SIMULATE); | 4728 AddSimulate(stmt->target()->ExitId(), REMOVABLE_SIMULATE); |
4729 } | 4729 } |
4730 environment()->BindContext(context); | 4730 environment()->BindContext(context); |
4731 } | 4731 } |
4732 Goto(break_block); | 4732 Goto(break_block); |
4733 set_current_block(NULL); | 4733 set_current_block(NULL); |
4734 } | 4734 } |
4735 | 4735 |
4736 | 4736 |
4737 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { | 4737 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
4738 ASSERT(!HasStackOverflow()); | 4738 DCHECK(!HasStackOverflow()); |
4739 ASSERT(current_block() != NULL); | 4739 DCHECK(current_block() != NULL); |
4740 ASSERT(current_block()->HasPredecessor()); | 4740 DCHECK(current_block()->HasPredecessor()); |
4741 FunctionState* state = function_state(); | 4741 FunctionState* state = function_state(); |
4742 AstContext* context = call_context(); | 4742 AstContext* context = call_context(); |
4743 if (context == NULL) { | 4743 if (context == NULL) { |
4744 // Not an inlined return, so an actual one. | 4744 // Not an inlined return, so an actual one. |
4745 CHECK_ALIVE(VisitForValue(stmt->expression())); | 4745 CHECK_ALIVE(VisitForValue(stmt->expression())); |
4746 HValue* result = environment()->Pop(); | 4746 HValue* result = environment()->Pop(); |
4747 Add<HReturn>(result); | 4747 Add<HReturn>(result); |
4748 } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { | 4748 } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { |
4749 // Return from an inlined construct call. In a test context the return value | 4749 // Return from an inlined construct call. In a test context the return value |
4750 // will always evaluate to true, in a value context the return value needs | 4750 // will always evaluate to true, in a value context the return value needs |
4751 // to be a JSObject. | 4751 // to be a JSObject. |
4752 if (context->IsTest()) { | 4752 if (context->IsTest()) { |
4753 TestContext* test = TestContext::cast(context); | 4753 TestContext* test = TestContext::cast(context); |
4754 CHECK_ALIVE(VisitForEffect(stmt->expression())); | 4754 CHECK_ALIVE(VisitForEffect(stmt->expression())); |
4755 Goto(test->if_true(), state); | 4755 Goto(test->if_true(), state); |
4756 } else if (context->IsEffect()) { | 4756 } else if (context->IsEffect()) { |
4757 CHECK_ALIVE(VisitForEffect(stmt->expression())); | 4757 CHECK_ALIVE(VisitForEffect(stmt->expression())); |
4758 Goto(function_return(), state); | 4758 Goto(function_return(), state); |
4759 } else { | 4759 } else { |
4760 ASSERT(context->IsValue()); | 4760 DCHECK(context->IsValue()); |
4761 CHECK_ALIVE(VisitForValue(stmt->expression())); | 4761 CHECK_ALIVE(VisitForValue(stmt->expression())); |
4762 HValue* return_value = Pop(); | 4762 HValue* return_value = Pop(); |
4763 HValue* receiver = environment()->arguments_environment()->Lookup(0); | 4763 HValue* receiver = environment()->arguments_environment()->Lookup(0); |
4764 HHasInstanceTypeAndBranch* typecheck = | 4764 HHasInstanceTypeAndBranch* typecheck = |
4765 New<HHasInstanceTypeAndBranch>(return_value, | 4765 New<HHasInstanceTypeAndBranch>(return_value, |
4766 FIRST_SPEC_OBJECT_TYPE, | 4766 FIRST_SPEC_OBJECT_TYPE, |
4767 LAST_SPEC_OBJECT_TYPE); | 4767 LAST_SPEC_OBJECT_TYPE); |
4768 HBasicBlock* if_spec_object = graph()->CreateBasicBlock(); | 4768 HBasicBlock* if_spec_object = graph()->CreateBasicBlock(); |
4769 HBasicBlock* not_spec_object = graph()->CreateBasicBlock(); | 4769 HBasicBlock* not_spec_object = graph()->CreateBasicBlock(); |
4770 typecheck->SetSuccessorAt(0, if_spec_object); | 4770 typecheck->SetSuccessorAt(0, if_spec_object); |
4771 typecheck->SetSuccessorAt(1, not_spec_object); | 4771 typecheck->SetSuccessorAt(1, not_spec_object); |
4772 FinishCurrentBlock(typecheck); | 4772 FinishCurrentBlock(typecheck); |
4773 AddLeaveInlined(if_spec_object, return_value, state); | 4773 AddLeaveInlined(if_spec_object, return_value, state); |
4774 AddLeaveInlined(not_spec_object, receiver, state); | 4774 AddLeaveInlined(not_spec_object, receiver, state); |
4775 } | 4775 } |
4776 } else if (state->inlining_kind() == SETTER_CALL_RETURN) { | 4776 } else if (state->inlining_kind() == SETTER_CALL_RETURN) { |
4777 // Return from an inlined setter call. The returned value is never used, the | 4777 // Return from an inlined setter call. The returned value is never used, the |
4778 // value of an assignment is always the value of the RHS of the assignment. | 4778 // value of an assignment is always the value of the RHS of the assignment. |
4779 CHECK_ALIVE(VisitForEffect(stmt->expression())); | 4779 CHECK_ALIVE(VisitForEffect(stmt->expression())); |
4780 if (context->IsTest()) { | 4780 if (context->IsTest()) { |
4781 HValue* rhs = environment()->arguments_environment()->Lookup(1); | 4781 HValue* rhs = environment()->arguments_environment()->Lookup(1); |
4782 context->ReturnValue(rhs); | 4782 context->ReturnValue(rhs); |
4783 } else if (context->IsEffect()) { | 4783 } else if (context->IsEffect()) { |
4784 Goto(function_return(), state); | 4784 Goto(function_return(), state); |
4785 } else { | 4785 } else { |
4786 ASSERT(context->IsValue()); | 4786 DCHECK(context->IsValue()); |
4787 HValue* rhs = environment()->arguments_environment()->Lookup(1); | 4787 HValue* rhs = environment()->arguments_environment()->Lookup(1); |
4788 AddLeaveInlined(rhs, state); | 4788 AddLeaveInlined(rhs, state); |
4789 } | 4789 } |
4790 } else { | 4790 } else { |
4791 // Return from a normal inlined function. Visit the subexpression in the | 4791 // Return from a normal inlined function. Visit the subexpression in the |
4792 // expression context of the call. | 4792 // expression context of the call. |
4793 if (context->IsTest()) { | 4793 if (context->IsTest()) { |
4794 TestContext* test = TestContext::cast(context); | 4794 TestContext* test = TestContext::cast(context); |
4795 VisitForControl(stmt->expression(), test->if_true(), test->if_false()); | 4795 VisitForControl(stmt->expression(), test->if_true(), test->if_false()); |
4796 } else if (context->IsEffect()) { | 4796 } else if (context->IsEffect()) { |
4797 // Visit in value context and ignore the result. This is needed to keep | 4797 // Visit in value context and ignore the result. This is needed to keep |
4798 // environment in sync with full-codegen since some visitors (e.g. | 4798 // environment in sync with full-codegen since some visitors (e.g. |
4799 // VisitCountOperation) use the operand stack differently depending on | 4799 // VisitCountOperation) use the operand stack differently depending on |
4800 // context. | 4800 // context. |
4801 CHECK_ALIVE(VisitForValue(stmt->expression())); | 4801 CHECK_ALIVE(VisitForValue(stmt->expression())); |
4802 Pop(); | 4802 Pop(); |
4803 Goto(function_return(), state); | 4803 Goto(function_return(), state); |
4804 } else { | 4804 } else { |
4805 ASSERT(context->IsValue()); | 4805 DCHECK(context->IsValue()); |
4806 CHECK_ALIVE(VisitForValue(stmt->expression())); | 4806 CHECK_ALIVE(VisitForValue(stmt->expression())); |
4807 AddLeaveInlined(Pop(), state); | 4807 AddLeaveInlined(Pop(), state); |
4808 } | 4808 } |
4809 } | 4809 } |
4810 set_current_block(NULL); | 4810 set_current_block(NULL); |
4811 } | 4811 } |
4812 | 4812 |
4813 | 4813 |
4814 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) { | 4814 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) { |
4815 ASSERT(!HasStackOverflow()); | 4815 DCHECK(!HasStackOverflow()); |
4816 ASSERT(current_block() != NULL); | 4816 DCHECK(current_block() != NULL); |
4817 ASSERT(current_block()->HasPredecessor()); | 4817 DCHECK(current_block()->HasPredecessor()); |
4818 return Bailout(kWithStatement); | 4818 return Bailout(kWithStatement); |
4819 } | 4819 } |
4820 | 4820 |
4821 | 4821 |
4822 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { | 4822 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { |
4823 ASSERT(!HasStackOverflow()); | 4823 DCHECK(!HasStackOverflow()); |
4824 ASSERT(current_block() != NULL); | 4824 DCHECK(current_block() != NULL); |
4825 ASSERT(current_block()->HasPredecessor()); | 4825 DCHECK(current_block()->HasPredecessor()); |
4826 | 4826 |
4827 // We only optimize switch statements with a bounded number of clauses. | 4827 // We only optimize switch statements with a bounded number of clauses. |
4828 const int kCaseClauseLimit = 128; | 4828 const int kCaseClauseLimit = 128; |
4829 ZoneList<CaseClause*>* clauses = stmt->cases(); | 4829 ZoneList<CaseClause*>* clauses = stmt->cases(); |
4830 int clause_count = clauses->length(); | 4830 int clause_count = clauses->length(); |
4831 ZoneList<HBasicBlock*> body_blocks(clause_count, zone()); | 4831 ZoneList<HBasicBlock*> body_blocks(clause_count, zone()); |
4832 if (clause_count > kCaseClauseLimit) { | 4832 if (clause_count > kCaseClauseLimit) { |
4833 return Bailout(kSwitchStatementTooManyClauses); | 4833 return Bailout(kSwitchStatementTooManyClauses); |
4834 } | 4834 } |
4835 | 4835 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4927 set_current_block(break_block); | 4927 set_current_block(break_block); |
4928 } | 4928 } |
4929 } | 4929 } |
4930 | 4930 |
4931 | 4931 |
4932 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, | 4932 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, |
4933 HBasicBlock* loop_entry) { | 4933 HBasicBlock* loop_entry) { |
4934 Add<HSimulate>(stmt->StackCheckId()); | 4934 Add<HSimulate>(stmt->StackCheckId()); |
4935 HStackCheck* stack_check = | 4935 HStackCheck* stack_check = |
4936 HStackCheck::cast(Add<HStackCheck>(HStackCheck::kBackwardsBranch)); | 4936 HStackCheck::cast(Add<HStackCheck>(HStackCheck::kBackwardsBranch)); |
4937 ASSERT(loop_entry->IsLoopHeader()); | 4937 DCHECK(loop_entry->IsLoopHeader()); |
4938 loop_entry->loop_information()->set_stack_check(stack_check); | 4938 loop_entry->loop_information()->set_stack_check(stack_check); |
4939 CHECK_BAILOUT(Visit(stmt->body())); | 4939 CHECK_BAILOUT(Visit(stmt->body())); |
4940 } | 4940 } |
4941 | 4941 |
4942 | 4942 |
4943 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { | 4943 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
4944 ASSERT(!HasStackOverflow()); | 4944 DCHECK(!HasStackOverflow()); |
4945 ASSERT(current_block() != NULL); | 4945 DCHECK(current_block() != NULL); |
4946 ASSERT(current_block()->HasPredecessor()); | 4946 DCHECK(current_block()->HasPredecessor()); |
4947 ASSERT(current_block() != NULL); | 4947 DCHECK(current_block() != NULL); |
4948 HBasicBlock* loop_entry = BuildLoopEntry(stmt); | 4948 HBasicBlock* loop_entry = BuildLoopEntry(stmt); |
4949 | 4949 |
4950 BreakAndContinueInfo break_info(stmt, scope()); | 4950 BreakAndContinueInfo break_info(stmt, scope()); |
4951 { | 4951 { |
4952 BreakAndContinueScope push(&break_info, this); | 4952 BreakAndContinueScope push(&break_info, this); |
4953 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry)); | 4953 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry)); |
4954 } | 4954 } |
4955 HBasicBlock* body_exit = | 4955 HBasicBlock* body_exit = |
4956 JoinContinue(stmt, current_block(), break_info.continue_block()); | 4956 JoinContinue(stmt, current_block(), break_info.continue_block()); |
4957 HBasicBlock* loop_successor = NULL; | 4957 HBasicBlock* loop_successor = NULL; |
(...skipping 24 matching lines...) Expand all Loading... |
4982 HBasicBlock* loop_exit = CreateLoop(stmt, | 4982 HBasicBlock* loop_exit = CreateLoop(stmt, |
4983 loop_entry, | 4983 loop_entry, |
4984 body_exit, | 4984 body_exit, |
4985 loop_successor, | 4985 loop_successor, |
4986 break_info.break_block()); | 4986 break_info.break_block()); |
4987 set_current_block(loop_exit); | 4987 set_current_block(loop_exit); |
4988 } | 4988 } |
4989 | 4989 |
4990 | 4990 |
4991 void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { | 4991 void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { |
4992 ASSERT(!HasStackOverflow()); | 4992 DCHECK(!HasStackOverflow()); |
4993 ASSERT(current_block() != NULL); | 4993 DCHECK(current_block() != NULL); |
4994 ASSERT(current_block()->HasPredecessor()); | 4994 DCHECK(current_block()->HasPredecessor()); |
4995 ASSERT(current_block() != NULL); | 4995 DCHECK(current_block() != NULL); |
4996 HBasicBlock* loop_entry = BuildLoopEntry(stmt); | 4996 HBasicBlock* loop_entry = BuildLoopEntry(stmt); |
4997 | 4997 |
4998 // If the condition is constant true, do not generate a branch. | 4998 // If the condition is constant true, do not generate a branch. |
4999 HBasicBlock* loop_successor = NULL; | 4999 HBasicBlock* loop_successor = NULL; |
5000 if (!stmt->cond()->ToBooleanIsTrue()) { | 5000 if (!stmt->cond()->ToBooleanIsTrue()) { |
5001 HBasicBlock* body_entry = graph()->CreateBasicBlock(); | 5001 HBasicBlock* body_entry = graph()->CreateBasicBlock(); |
5002 loop_successor = graph()->CreateBasicBlock(); | 5002 loop_successor = graph()->CreateBasicBlock(); |
5003 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); | 5003 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); |
5004 if (body_entry->HasPredecessor()) { | 5004 if (body_entry->HasPredecessor()) { |
5005 body_entry->SetJoinId(stmt->BodyId()); | 5005 body_entry->SetJoinId(stmt->BodyId()); |
(...skipping 16 matching lines...) Expand all Loading... |
5022 HBasicBlock* loop_exit = CreateLoop(stmt, | 5022 HBasicBlock* loop_exit = CreateLoop(stmt, |
5023 loop_entry, | 5023 loop_entry, |
5024 body_exit, | 5024 body_exit, |
5025 loop_successor, | 5025 loop_successor, |
5026 break_info.break_block()); | 5026 break_info.break_block()); |
5027 set_current_block(loop_exit); | 5027 set_current_block(loop_exit); |
5028 } | 5028 } |
5029 | 5029 |
5030 | 5030 |
5031 void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) { | 5031 void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) { |
5032 ASSERT(!HasStackOverflow()); | 5032 DCHECK(!HasStackOverflow()); |
5033 ASSERT(current_block() != NULL); | 5033 DCHECK(current_block() != NULL); |
5034 ASSERT(current_block()->HasPredecessor()); | 5034 DCHECK(current_block()->HasPredecessor()); |
5035 if (stmt->init() != NULL) { | 5035 if (stmt->init() != NULL) { |
5036 CHECK_ALIVE(Visit(stmt->init())); | 5036 CHECK_ALIVE(Visit(stmt->init())); |
5037 } | 5037 } |
5038 ASSERT(current_block() != NULL); | 5038 DCHECK(current_block() != NULL); |
5039 HBasicBlock* loop_entry = BuildLoopEntry(stmt); | 5039 HBasicBlock* loop_entry = BuildLoopEntry(stmt); |
5040 | 5040 |
5041 HBasicBlock* loop_successor = NULL; | 5041 HBasicBlock* loop_successor = NULL; |
5042 if (stmt->cond() != NULL) { | 5042 if (stmt->cond() != NULL) { |
5043 HBasicBlock* body_entry = graph()->CreateBasicBlock(); | 5043 HBasicBlock* body_entry = graph()->CreateBasicBlock(); |
5044 loop_successor = graph()->CreateBasicBlock(); | 5044 loop_successor = graph()->CreateBasicBlock(); |
5045 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); | 5045 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); |
5046 if (body_entry->HasPredecessor()) { | 5046 if (body_entry->HasPredecessor()) { |
5047 body_entry->SetJoinId(stmt->BodyId()); | 5047 body_entry->SetJoinId(stmt->BodyId()); |
5048 set_current_block(body_entry); | 5048 set_current_block(body_entry); |
(...skipping 22 matching lines...) Expand all Loading... |
5071 HBasicBlock* loop_exit = CreateLoop(stmt, | 5071 HBasicBlock* loop_exit = CreateLoop(stmt, |
5072 loop_entry, | 5072 loop_entry, |
5073 body_exit, | 5073 body_exit, |
5074 loop_successor, | 5074 loop_successor, |
5075 break_info.break_block()); | 5075 break_info.break_block()); |
5076 set_current_block(loop_exit); | 5076 set_current_block(loop_exit); |
5077 } | 5077 } |
5078 | 5078 |
5079 | 5079 |
5080 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) { | 5080 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
5081 ASSERT(!HasStackOverflow()); | 5081 DCHECK(!HasStackOverflow()); |
5082 ASSERT(current_block() != NULL); | 5082 DCHECK(current_block() != NULL); |
5083 ASSERT(current_block()->HasPredecessor()); | 5083 DCHECK(current_block()->HasPredecessor()); |
5084 | 5084 |
5085 if (!FLAG_optimize_for_in) { | 5085 if (!FLAG_optimize_for_in) { |
5086 return Bailout(kForInStatementOptimizationIsDisabled); | 5086 return Bailout(kForInStatementOptimizationIsDisabled); |
5087 } | 5087 } |
5088 | 5088 |
5089 if (stmt->for_in_type() != ForInStatement::FAST_FOR_IN) { | 5089 if (stmt->for_in_type() != ForInStatement::FAST_FOR_IN) { |
5090 return Bailout(kForInStatementIsNotFastCase); | 5090 return Bailout(kForInStatementIsNotFastCase); |
5091 } | 5091 } |
5092 | 5092 |
5093 if (!stmt->each()->IsVariableProxy() || | 5093 if (!stmt->each()->IsVariableProxy() || |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5177 loop_entry, | 5177 loop_entry, |
5178 body_exit, | 5178 body_exit, |
5179 loop_successor, | 5179 loop_successor, |
5180 break_info.break_block()); | 5180 break_info.break_block()); |
5181 | 5181 |
5182 set_current_block(loop_exit); | 5182 set_current_block(loop_exit); |
5183 } | 5183 } |
5184 | 5184 |
5185 | 5185 |
5186 void HOptimizedGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) { | 5186 void HOptimizedGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) { |
5187 ASSERT(!HasStackOverflow()); | 5187 DCHECK(!HasStackOverflow()); |
5188 ASSERT(current_block() != NULL); | 5188 DCHECK(current_block() != NULL); |
5189 ASSERT(current_block()->HasPredecessor()); | 5189 DCHECK(current_block()->HasPredecessor()); |
5190 return Bailout(kForOfStatement); | 5190 return Bailout(kForOfStatement); |
5191 } | 5191 } |
5192 | 5192 |
5193 | 5193 |
5194 void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { | 5194 void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { |
5195 ASSERT(!HasStackOverflow()); | 5195 DCHECK(!HasStackOverflow()); |
5196 ASSERT(current_block() != NULL); | 5196 DCHECK(current_block() != NULL); |
5197 ASSERT(current_block()->HasPredecessor()); | 5197 DCHECK(current_block()->HasPredecessor()); |
5198 return Bailout(kTryCatchStatement); | 5198 return Bailout(kTryCatchStatement); |
5199 } | 5199 } |
5200 | 5200 |
5201 | 5201 |
5202 void HOptimizedGraphBuilder::VisitTryFinallyStatement( | 5202 void HOptimizedGraphBuilder::VisitTryFinallyStatement( |
5203 TryFinallyStatement* stmt) { | 5203 TryFinallyStatement* stmt) { |
5204 ASSERT(!HasStackOverflow()); | 5204 DCHECK(!HasStackOverflow()); |
5205 ASSERT(current_block() != NULL); | 5205 DCHECK(current_block() != NULL); |
5206 ASSERT(current_block()->HasPredecessor()); | 5206 DCHECK(current_block()->HasPredecessor()); |
5207 return Bailout(kTryFinallyStatement); | 5207 return Bailout(kTryFinallyStatement); |
5208 } | 5208 } |
5209 | 5209 |
5210 | 5210 |
5211 void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { | 5211 void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { |
5212 ASSERT(!HasStackOverflow()); | 5212 DCHECK(!HasStackOverflow()); |
5213 ASSERT(current_block() != NULL); | 5213 DCHECK(current_block() != NULL); |
5214 ASSERT(current_block()->HasPredecessor()); | 5214 DCHECK(current_block()->HasPredecessor()); |
5215 return Bailout(kDebuggerStatement); | 5215 return Bailout(kDebuggerStatement); |
5216 } | 5216 } |
5217 | 5217 |
5218 | 5218 |
5219 void HOptimizedGraphBuilder::VisitCaseClause(CaseClause* clause) { | 5219 void HOptimizedGraphBuilder::VisitCaseClause(CaseClause* clause) { |
5220 UNREACHABLE(); | 5220 UNREACHABLE(); |
5221 } | 5221 } |
5222 | 5222 |
5223 | 5223 |
5224 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { | 5224 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { |
5225 ASSERT(!HasStackOverflow()); | 5225 DCHECK(!HasStackOverflow()); |
5226 ASSERT(current_block() != NULL); | 5226 DCHECK(current_block() != NULL); |
5227 ASSERT(current_block()->HasPredecessor()); | 5227 DCHECK(current_block()->HasPredecessor()); |
5228 Handle<SharedFunctionInfo> shared_info = expr->shared_info(); | 5228 Handle<SharedFunctionInfo> shared_info = expr->shared_info(); |
5229 if (shared_info.is_null()) { | 5229 if (shared_info.is_null()) { |
5230 shared_info = | 5230 shared_info = |
5231 Compiler::BuildFunctionInfo(expr, current_info()->script(), top_info()); | 5231 Compiler::BuildFunctionInfo(expr, current_info()->script(), top_info()); |
5232 } | 5232 } |
5233 // We also have a stack overflow if the recursive compilation did. | 5233 // We also have a stack overflow if the recursive compilation did. |
5234 if (HasStackOverflow()) return; | 5234 if (HasStackOverflow()) return; |
5235 HFunctionLiteral* instr = | 5235 HFunctionLiteral* instr = |
5236 New<HFunctionLiteral>(shared_info, expr->pretenure()); | 5236 New<HFunctionLiteral>(shared_info, expr->pretenure()); |
5237 return ast_context()->ReturnInstruction(instr, expr->id()); | 5237 return ast_context()->ReturnInstruction(instr, expr->id()); |
5238 } | 5238 } |
5239 | 5239 |
5240 | 5240 |
5241 void HOptimizedGraphBuilder::VisitNativeFunctionLiteral( | 5241 void HOptimizedGraphBuilder::VisitNativeFunctionLiteral( |
5242 NativeFunctionLiteral* expr) { | 5242 NativeFunctionLiteral* expr) { |
5243 ASSERT(!HasStackOverflow()); | 5243 DCHECK(!HasStackOverflow()); |
5244 ASSERT(current_block() != NULL); | 5244 DCHECK(current_block() != NULL); |
5245 ASSERT(current_block()->HasPredecessor()); | 5245 DCHECK(current_block()->HasPredecessor()); |
5246 return Bailout(kNativeFunctionLiteral); | 5246 return Bailout(kNativeFunctionLiteral); |
5247 } | 5247 } |
5248 | 5248 |
5249 | 5249 |
5250 void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) { | 5250 void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) { |
5251 ASSERT(!HasStackOverflow()); | 5251 DCHECK(!HasStackOverflow()); |
5252 ASSERT(current_block() != NULL); | 5252 DCHECK(current_block() != NULL); |
5253 ASSERT(current_block()->HasPredecessor()); | 5253 DCHECK(current_block()->HasPredecessor()); |
5254 HBasicBlock* cond_true = graph()->CreateBasicBlock(); | 5254 HBasicBlock* cond_true = graph()->CreateBasicBlock(); |
5255 HBasicBlock* cond_false = graph()->CreateBasicBlock(); | 5255 HBasicBlock* cond_false = graph()->CreateBasicBlock(); |
5256 CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false)); | 5256 CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false)); |
5257 | 5257 |
5258 // Visit the true and false subexpressions in the same AST context as the | 5258 // Visit the true and false subexpressions in the same AST context as the |
5259 // whole expression. | 5259 // whole expression. |
5260 if (cond_true->HasPredecessor()) { | 5260 if (cond_true->HasPredecessor()) { |
5261 cond_true->SetJoinId(expr->ThenId()); | 5261 cond_true->SetJoinId(expr->ThenId()); |
5262 set_current_block(cond_true); | 5262 set_current_block(cond_true); |
5263 CHECK_BAILOUT(Visit(expr->then_expression())); | 5263 CHECK_BAILOUT(Visit(expr->then_expression())); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5297 (access_type == STORE && lookup->IsReadOnly()) || | 5297 (access_type == STORE && lookup->IsReadOnly()) || |
5298 lookup->holder() != *global) { | 5298 lookup->holder() != *global) { |
5299 return kUseGeneric; | 5299 return kUseGeneric; |
5300 } | 5300 } |
5301 | 5301 |
5302 return kUseCell; | 5302 return kUseCell; |
5303 } | 5303 } |
5304 | 5304 |
5305 | 5305 |
5306 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { | 5306 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { |
5307 ASSERT(var->IsContextSlot()); | 5307 DCHECK(var->IsContextSlot()); |
5308 HValue* context = environment()->context(); | 5308 HValue* context = environment()->context(); |
5309 int length = scope()->ContextChainLength(var->scope()); | 5309 int length = scope()->ContextChainLength(var->scope()); |
5310 while (length-- > 0) { | 5310 while (length-- > 0) { |
5311 context = Add<HLoadNamedField>( | 5311 context = Add<HLoadNamedField>( |
5312 context, static_cast<HValue*>(NULL), | 5312 context, static_cast<HValue*>(NULL), |
5313 HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX)); | 5313 HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX)); |
5314 } | 5314 } |
5315 return context; | 5315 return context; |
5316 } | 5316 } |
5317 | 5317 |
5318 | 5318 |
5319 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 5319 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
5320 if (expr->is_this()) { | 5320 if (expr->is_this()) { |
5321 current_info()->set_this_has_uses(true); | 5321 current_info()->set_this_has_uses(true); |
5322 } | 5322 } |
5323 | 5323 |
5324 ASSERT(!HasStackOverflow()); | 5324 DCHECK(!HasStackOverflow()); |
5325 ASSERT(current_block() != NULL); | 5325 DCHECK(current_block() != NULL); |
5326 ASSERT(current_block()->HasPredecessor()); | 5326 DCHECK(current_block()->HasPredecessor()); |
5327 Variable* variable = expr->var(); | 5327 Variable* variable = expr->var(); |
5328 switch (variable->location()) { | 5328 switch (variable->location()) { |
5329 case Variable::UNALLOCATED: { | 5329 case Variable::UNALLOCATED: { |
5330 if (IsLexicalVariableMode(variable->mode())) { | 5330 if (IsLexicalVariableMode(variable->mode())) { |
5331 // TODO(rossberg): should this be an ASSERT? | 5331 // TODO(rossberg): should this be an DCHECK? |
5332 return Bailout(kReferenceToGlobalLexicalVariable); | 5332 return Bailout(kReferenceToGlobalLexicalVariable); |
5333 } | 5333 } |
5334 // Handle known global constants like 'undefined' specially to avoid a | 5334 // Handle known global constants like 'undefined' specially to avoid a |
5335 // load from a global cell for them. | 5335 // load from a global cell for them. |
5336 Handle<Object> constant_value = | 5336 Handle<Object> constant_value = |
5337 isolate()->factory()->GlobalConstantFor(variable->name()); | 5337 isolate()->factory()->GlobalConstantFor(variable->name()); |
5338 if (!constant_value.is_null()) { | 5338 if (!constant_value.is_null()) { |
5339 HConstant* instr = New<HConstant>(constant_value); | 5339 HConstant* instr = New<HConstant>(constant_value); |
5340 return ast_context()->ReturnInstruction(instr, expr->id()); | 5340 return ast_context()->ReturnInstruction(instr, expr->id()); |
5341 } | 5341 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5381 expr->VariableFeedbackSlot()); | 5381 expr->VariableFeedbackSlot()); |
5382 } | 5382 } |
5383 return ast_context()->ReturnInstruction(instr, expr->id()); | 5383 return ast_context()->ReturnInstruction(instr, expr->id()); |
5384 } | 5384 } |
5385 } | 5385 } |
5386 | 5386 |
5387 case Variable::PARAMETER: | 5387 case Variable::PARAMETER: |
5388 case Variable::LOCAL: { | 5388 case Variable::LOCAL: { |
5389 HValue* value = LookupAndMakeLive(variable); | 5389 HValue* value = LookupAndMakeLive(variable); |
5390 if (value == graph()->GetConstantHole()) { | 5390 if (value == graph()->GetConstantHole()) { |
5391 ASSERT(IsDeclaredVariableMode(variable->mode()) && | 5391 DCHECK(IsDeclaredVariableMode(variable->mode()) && |
5392 variable->mode() != VAR); | 5392 variable->mode() != VAR); |
5393 return Bailout(kReferenceToUninitializedVariable); | 5393 return Bailout(kReferenceToUninitializedVariable); |
5394 } | 5394 } |
5395 return ast_context()->ReturnValue(value); | 5395 return ast_context()->ReturnValue(value); |
5396 } | 5396 } |
5397 | 5397 |
5398 case Variable::CONTEXT: { | 5398 case Variable::CONTEXT: { |
5399 HValue* context = BuildContextChainWalk(variable); | 5399 HValue* context = BuildContextChainWalk(variable); |
5400 HLoadContextSlot::Mode mode; | 5400 HLoadContextSlot::Mode mode; |
5401 switch (variable->mode()) { | 5401 switch (variable->mode()) { |
(...skipping 13 matching lines...) Expand all Loading... |
5415 return ast_context()->ReturnInstruction(instr, expr->id()); | 5415 return ast_context()->ReturnInstruction(instr, expr->id()); |
5416 } | 5416 } |
5417 | 5417 |
5418 case Variable::LOOKUP: | 5418 case Variable::LOOKUP: |
5419 return Bailout(kReferenceToAVariableWhichRequiresDynamicLookup); | 5419 return Bailout(kReferenceToAVariableWhichRequiresDynamicLookup); |
5420 } | 5420 } |
5421 } | 5421 } |
5422 | 5422 |
5423 | 5423 |
5424 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) { | 5424 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) { |
5425 ASSERT(!HasStackOverflow()); | 5425 DCHECK(!HasStackOverflow()); |
5426 ASSERT(current_block() != NULL); | 5426 DCHECK(current_block() != NULL); |
5427 ASSERT(current_block()->HasPredecessor()); | 5427 DCHECK(current_block()->HasPredecessor()); |
5428 HConstant* instr = New<HConstant>(expr->value()); | 5428 HConstant* instr = New<HConstant>(expr->value()); |
5429 return ast_context()->ReturnInstruction(instr, expr->id()); | 5429 return ast_context()->ReturnInstruction(instr, expr->id()); |
5430 } | 5430 } |
5431 | 5431 |
5432 | 5432 |
5433 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { | 5433 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { |
5434 ASSERT(!HasStackOverflow()); | 5434 DCHECK(!HasStackOverflow()); |
5435 ASSERT(current_block() != NULL); | 5435 DCHECK(current_block() != NULL); |
5436 ASSERT(current_block()->HasPredecessor()); | 5436 DCHECK(current_block()->HasPredecessor()); |
5437 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 5437 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
5438 Handle<FixedArray> literals(closure->literals()); | 5438 Handle<FixedArray> literals(closure->literals()); |
5439 HRegExpLiteral* instr = New<HRegExpLiteral>(literals, | 5439 HRegExpLiteral* instr = New<HRegExpLiteral>(literals, |
5440 expr->pattern(), | 5440 expr->pattern(), |
5441 expr->flags(), | 5441 expr->flags(), |
5442 expr->literal_index()); | 5442 expr->literal_index()); |
5443 return ast_context()->ReturnInstruction(instr, expr->id()); | 5443 return ast_context()->ReturnInstruction(instr, expr->id()); |
5444 } | 5444 } |
5445 | 5445 |
5446 | 5446 |
(...skipping 11 matching lines...) Expand all Loading... |
5458 // all limits to be considered for fast deep-copying and computes the total | 5458 // all limits to be considered for fast deep-copying and computes the total |
5459 // size of all objects that are part of the graph. | 5459 // size of all objects that are part of the graph. |
5460 static bool IsFastLiteral(Handle<JSObject> boilerplate, | 5460 static bool IsFastLiteral(Handle<JSObject> boilerplate, |
5461 int max_depth, | 5461 int max_depth, |
5462 int* max_properties) { | 5462 int* max_properties) { |
5463 if (boilerplate->map()->is_deprecated() && | 5463 if (boilerplate->map()->is_deprecated() && |
5464 !JSObject::TryMigrateInstance(boilerplate)) { | 5464 !JSObject::TryMigrateInstance(boilerplate)) { |
5465 return false; | 5465 return false; |
5466 } | 5466 } |
5467 | 5467 |
5468 ASSERT(max_depth >= 0 && *max_properties >= 0); | 5468 DCHECK(max_depth >= 0 && *max_properties >= 0); |
5469 if (max_depth == 0) return false; | 5469 if (max_depth == 0) return false; |
5470 | 5470 |
5471 Isolate* isolate = boilerplate->GetIsolate(); | 5471 Isolate* isolate = boilerplate->GetIsolate(); |
5472 Handle<FixedArrayBase> elements(boilerplate->elements()); | 5472 Handle<FixedArrayBase> elements(boilerplate->elements()); |
5473 if (elements->length() > 0 && | 5473 if (elements->length() > 0 && |
5474 elements->map() != isolate->heap()->fixed_cow_array_map()) { | 5474 elements->map() != isolate->heap()->fixed_cow_array_map()) { |
5475 if (boilerplate->HasFastObjectElements()) { | 5475 if (boilerplate->HasFastObjectElements()) { |
5476 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); | 5476 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); |
5477 int length = elements->length(); | 5477 int length = elements->length(); |
5478 for (int i = 0; i < length; i++) { | 5478 for (int i = 0; i < length; i++) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5513 return false; | 5513 return false; |
5514 } | 5514 } |
5515 } | 5515 } |
5516 } | 5516 } |
5517 } | 5517 } |
5518 return true; | 5518 return true; |
5519 } | 5519 } |
5520 | 5520 |
5521 | 5521 |
5522 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { | 5522 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
5523 ASSERT(!HasStackOverflow()); | 5523 DCHECK(!HasStackOverflow()); |
5524 ASSERT(current_block() != NULL); | 5524 DCHECK(current_block() != NULL); |
5525 ASSERT(current_block()->HasPredecessor()); | 5525 DCHECK(current_block()->HasPredecessor()); |
5526 expr->BuildConstantProperties(isolate()); | 5526 expr->BuildConstantProperties(isolate()); |
5527 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 5527 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
5528 HInstruction* literal; | 5528 HInstruction* literal; |
5529 | 5529 |
5530 // Check whether to use fast or slow deep-copying for boilerplate. | 5530 // Check whether to use fast or slow deep-copying for boilerplate. |
5531 int max_properties = kMaxFastLiteralProperties; | 5531 int max_properties = kMaxFastLiteralProperties; |
5532 Handle<Object> literals_cell(closure->literals()->get(expr->literal_index()), | 5532 Handle<Object> literals_cell(closure->literals()->get(expr->literal_index()), |
5533 isolate()); | 5533 isolate()); |
5534 Handle<AllocationSite> site; | 5534 Handle<AllocationSite> site; |
5535 Handle<JSObject> boilerplate; | 5535 Handle<JSObject> boilerplate; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5578 | 5578 |
5579 for (int i = 0; i < expr->properties()->length(); i++) { | 5579 for (int i = 0; i < expr->properties()->length(); i++) { |
5580 ObjectLiteral::Property* property = expr->properties()->at(i); | 5580 ObjectLiteral::Property* property = expr->properties()->at(i); |
5581 if (property->IsCompileTimeValue()) continue; | 5581 if (property->IsCompileTimeValue()) continue; |
5582 | 5582 |
5583 Literal* key = property->key(); | 5583 Literal* key = property->key(); |
5584 Expression* value = property->value(); | 5584 Expression* value = property->value(); |
5585 | 5585 |
5586 switch (property->kind()) { | 5586 switch (property->kind()) { |
5587 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 5587 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
5588 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); | 5588 DCHECK(!CompileTimeValue::IsCompileTimeValue(value)); |
5589 // Fall through. | 5589 // Fall through. |
5590 case ObjectLiteral::Property::COMPUTED: | 5590 case ObjectLiteral::Property::COMPUTED: |
5591 if (key->value()->IsInternalizedString()) { | 5591 if (key->value()->IsInternalizedString()) { |
5592 if (property->emit_store()) { | 5592 if (property->emit_store()) { |
5593 CHECK_ALIVE(VisitForValue(value)); | 5593 CHECK_ALIVE(VisitForValue(value)); |
5594 HValue* value = Pop(); | 5594 HValue* value = Pop(); |
5595 Handle<Map> map = property->GetReceiverType(); | 5595 Handle<Map> map = property->GetReceiverType(); |
5596 Handle<String> name = property->key()->AsPropertyName(); | 5596 Handle<String> name = property->key()->AsPropertyName(); |
5597 HInstruction* store; | 5597 HInstruction* store; |
5598 if (map.is_null()) { | 5598 if (map.is_null()) { |
5599 // If we don't know the monomorphic type, do a generic store. | 5599 // If we don't know the monomorphic type, do a generic store. |
5600 CHECK_ALIVE(store = BuildNamedGeneric( | 5600 CHECK_ALIVE(store = BuildNamedGeneric( |
5601 STORE, NULL, literal, name, value)); | 5601 STORE, NULL, literal, name, value)); |
5602 } else { | 5602 } else { |
5603 PropertyAccessInfo info(this, STORE, ToType(map), name); | 5603 PropertyAccessInfo info(this, STORE, ToType(map), name); |
5604 if (info.CanAccessMonomorphic()) { | 5604 if (info.CanAccessMonomorphic()) { |
5605 HValue* checked_literal = Add<HCheckMaps>(literal, map); | 5605 HValue* checked_literal = Add<HCheckMaps>(literal, map); |
5606 ASSERT(!info.lookup()->IsPropertyCallbacks()); | 5606 DCHECK(!info.lookup()->IsPropertyCallbacks()); |
5607 store = BuildMonomorphicAccess( | 5607 store = BuildMonomorphicAccess( |
5608 &info, literal, checked_literal, value, | 5608 &info, literal, checked_literal, value, |
5609 BailoutId::None(), BailoutId::None()); | 5609 BailoutId::None(), BailoutId::None()); |
5610 } else { | 5610 } else { |
5611 CHECK_ALIVE(store = BuildNamedGeneric( | 5611 CHECK_ALIVE(store = BuildNamedGeneric( |
5612 STORE, NULL, literal, name, value)); | 5612 STORE, NULL, literal, name, value)); |
5613 } | 5613 } |
5614 } | 5614 } |
5615 AddInstruction(store); | 5615 AddInstruction(store); |
5616 if (store->HasObservableSideEffects()) { | 5616 if (store->HasObservableSideEffects()) { |
(...skipping 21 matching lines...) Expand all Loading... |
5638 // (e.g. because of code motion). | 5638 // (e.g. because of code motion). |
5639 HToFastProperties* result = Add<HToFastProperties>(Pop()); | 5639 HToFastProperties* result = Add<HToFastProperties>(Pop()); |
5640 return ast_context()->ReturnValue(result); | 5640 return ast_context()->ReturnValue(result); |
5641 } else { | 5641 } else { |
5642 return ast_context()->ReturnValue(Pop()); | 5642 return ast_context()->ReturnValue(Pop()); |
5643 } | 5643 } |
5644 } | 5644 } |
5645 | 5645 |
5646 | 5646 |
5647 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { | 5647 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
5648 ASSERT(!HasStackOverflow()); | 5648 DCHECK(!HasStackOverflow()); |
5649 ASSERT(current_block() != NULL); | 5649 DCHECK(current_block() != NULL); |
5650 ASSERT(current_block()->HasPredecessor()); | 5650 DCHECK(current_block()->HasPredecessor()); |
5651 expr->BuildConstantElements(isolate()); | 5651 expr->BuildConstantElements(isolate()); |
5652 ZoneList<Expression*>* subexprs = expr->values(); | 5652 ZoneList<Expression*>* subexprs = expr->values(); |
5653 int length = subexprs->length(); | 5653 int length = subexprs->length(); |
5654 HInstruction* literal; | 5654 HInstruction* literal; |
5655 | 5655 |
5656 Handle<AllocationSite> site; | 5656 Handle<AllocationSite> site; |
5657 Handle<FixedArray> literals(environment()->closure()->literals(), isolate()); | 5657 Handle<FixedArray> literals(environment()->closure()->literals(), isolate()); |
5658 bool uninitialized = false; | 5658 bool uninitialized = false; |
5659 Handle<Object> literals_cell(literals->get(expr->literal_index()), | 5659 Handle<Object> literals_cell(literals->get(expr->literal_index()), |
5660 isolate()); | 5660 isolate()); |
(...skipping 14 matching lines...) Expand all Loading... |
5675 return Bailout(kArrayBoilerplateCreationFailed); | 5675 return Bailout(kArrayBoilerplateCreationFailed); |
5676 } | 5676 } |
5677 creation_context.ExitScope(site, boilerplate_object); | 5677 creation_context.ExitScope(site, boilerplate_object); |
5678 literals->set(expr->literal_index(), *site); | 5678 literals->set(expr->literal_index(), *site); |
5679 | 5679 |
5680 if (boilerplate_object->elements()->map() == | 5680 if (boilerplate_object->elements()->map() == |
5681 isolate()->heap()->fixed_cow_array_map()) { | 5681 isolate()->heap()->fixed_cow_array_map()) { |
5682 isolate()->counters()->cow_arrays_created_runtime()->Increment(); | 5682 isolate()->counters()->cow_arrays_created_runtime()->Increment(); |
5683 } | 5683 } |
5684 } else { | 5684 } else { |
5685 ASSERT(literals_cell->IsAllocationSite()); | 5685 DCHECK(literals_cell->IsAllocationSite()); |
5686 site = Handle<AllocationSite>::cast(literals_cell); | 5686 site = Handle<AllocationSite>::cast(literals_cell); |
5687 boilerplate_object = Handle<JSObject>( | 5687 boilerplate_object = Handle<JSObject>( |
5688 JSObject::cast(site->transition_info()), isolate()); | 5688 JSObject::cast(site->transition_info()), isolate()); |
5689 } | 5689 } |
5690 | 5690 |
5691 ASSERT(!boilerplate_object.is_null()); | 5691 DCHECK(!boilerplate_object.is_null()); |
5692 ASSERT(site->SitePointsToLiteral()); | 5692 DCHECK(site->SitePointsToLiteral()); |
5693 | 5693 |
5694 ElementsKind boilerplate_elements_kind = | 5694 ElementsKind boilerplate_elements_kind = |
5695 boilerplate_object->GetElementsKind(); | 5695 boilerplate_object->GetElementsKind(); |
5696 | 5696 |
5697 // Check whether to use fast or slow deep-copying for boilerplate. | 5697 // Check whether to use fast or slow deep-copying for boilerplate. |
5698 int max_properties = kMaxFastLiteralProperties; | 5698 int max_properties = kMaxFastLiteralProperties; |
5699 if (IsFastLiteral(boilerplate_object, | 5699 if (IsFastLiteral(boilerplate_object, |
5700 kMaxFastLiteralDepth, | 5700 kMaxFastLiteralDepth, |
5701 &max_properties)) { | 5701 &max_properties)) { |
5702 AllocationSiteUsageContext usage_context(isolate(), site, false); | 5702 AllocationSiteUsageContext usage_context(isolate(), site, false); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5794 info->lookup()->IsCacheable() && | 5794 info->lookup()->IsCacheable() && |
5795 info->lookup()->IsReadOnly() && info->lookup()->IsDontDelete()) { | 5795 info->lookup()->IsReadOnly() && info->lookup()->IsDontDelete()) { |
5796 Handle<Object> object( | 5796 Handle<Object> object( |
5797 HConstant::cast(checked_object->ActualValue())->handle(isolate())); | 5797 HConstant::cast(checked_object->ActualValue())->handle(isolate())); |
5798 | 5798 |
5799 if (object->IsJSObject()) { | 5799 if (object->IsJSObject()) { |
5800 LookupResult lookup(isolate()); | 5800 LookupResult lookup(isolate()); |
5801 Handle<JSObject>::cast(object)->Lookup(info->name(), &lookup); | 5801 Handle<JSObject>::cast(object)->Lookup(info->name(), &lookup); |
5802 Handle<Object> value(lookup.GetLazyValue(), isolate()); | 5802 Handle<Object> value(lookup.GetLazyValue(), isolate()); |
5803 | 5803 |
5804 ASSERT(!value->IsTheHole()); | 5804 DCHECK(!value->IsTheHole()); |
5805 return New<HConstant>(value); | 5805 return New<HConstant>(value); |
5806 } | 5806 } |
5807 } | 5807 } |
5808 | 5808 |
5809 HObjectAccess access = info->access(); | 5809 HObjectAccess access = info->access(); |
5810 if (access.representation().IsDouble()) { | 5810 if (access.representation().IsDouble()) { |
5811 // Load the heap number. | 5811 // Load the heap number. |
5812 checked_object = Add<HLoadNamedField>( | 5812 checked_object = Add<HLoadNamedField>( |
5813 checked_object, static_cast<HValue*>(NULL), | 5813 checked_object, static_cast<HValue*>(NULL), |
5814 access.WithRepresentation(Representation::Tagged())); | 5814 access.WithRepresentation(Representation::Tagged())); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5866 instr = New<HStoreNamedField>(heap_number, | 5866 instr = New<HStoreNamedField>(heap_number, |
5867 HObjectAccess::ForHeapNumberValue(), | 5867 HObjectAccess::ForHeapNumberValue(), |
5868 value, STORE_TO_INITIALIZED_ENTRY); | 5868 value, STORE_TO_INITIALIZED_ENTRY); |
5869 } | 5869 } |
5870 } else { | 5870 } else { |
5871 if (field_access.representation().IsHeapObject()) { | 5871 if (field_access.representation().IsHeapObject()) { |
5872 BuildCheckHeapObject(value); | 5872 BuildCheckHeapObject(value); |
5873 } | 5873 } |
5874 | 5874 |
5875 if (!info->field_maps()->is_empty()) { | 5875 if (!info->field_maps()->is_empty()) { |
5876 ASSERT(field_access.representation().IsHeapObject()); | 5876 DCHECK(field_access.representation().IsHeapObject()); |
5877 value = Add<HCheckMaps>(value, info->field_maps()); | 5877 value = Add<HCheckMaps>(value, info->field_maps()); |
5878 } | 5878 } |
5879 | 5879 |
5880 // This is a normal store. | 5880 // This is a normal store. |
5881 instr = New<HStoreNamedField>( | 5881 instr = New<HStoreNamedField>( |
5882 checked_object->ActualValue(), field_access, value, | 5882 checked_object->ActualValue(), field_access, value, |
5883 transition_to_field ? INITIALIZING_STORE : STORE_TO_INITIALIZED_ENTRY); | 5883 transition_to_field ? INITIALIZING_STORE : STORE_TO_INITIALIZED_ENTRY); |
5884 } | 5884 } |
5885 | 5885 |
5886 if (transition_to_field) { | 5886 if (transition_to_field) { |
5887 Handle<Map> transition(info->transition()); | 5887 Handle<Map> transition(info->transition()); |
5888 ASSERT(!transition->is_deprecated()); | 5888 DCHECK(!transition->is_deprecated()); |
5889 instr->SetTransition(Add<HConstant>(transition)); | 5889 instr->SetTransition(Add<HConstant>(transition)); |
5890 } | 5890 } |
5891 return instr; | 5891 return instr; |
5892 } | 5892 } |
5893 | 5893 |
5894 | 5894 |
5895 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible( | 5895 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible( |
5896 PropertyAccessInfo* info) { | 5896 PropertyAccessInfo* info) { |
5897 if (!CanInlinePropertyAccess(type_)) return false; | 5897 if (!CanInlinePropertyAccess(type_)) return false; |
5898 | 5898 |
(...skipping 23 matching lines...) Expand all Loading... |
5922 | 5922 |
5923 if (lookup_.IsPropertyCallbacks()) { | 5923 if (lookup_.IsPropertyCallbacks()) { |
5924 return accessor_.is_identical_to(info->accessor_) && | 5924 return accessor_.is_identical_to(info->accessor_) && |
5925 api_holder_.is_identical_to(info->api_holder_); | 5925 api_holder_.is_identical_to(info->api_holder_); |
5926 } | 5926 } |
5927 | 5927 |
5928 if (lookup_.IsConstant()) { | 5928 if (lookup_.IsConstant()) { |
5929 return constant_.is_identical_to(info->constant_); | 5929 return constant_.is_identical_to(info->constant_); |
5930 } | 5930 } |
5931 | 5931 |
5932 ASSERT(lookup_.IsField()); | 5932 DCHECK(lookup_.IsField()); |
5933 if (!info->lookup_.IsField()) return false; | 5933 if (!info->lookup_.IsField()) return false; |
5934 | 5934 |
5935 Representation r = access_.representation(); | 5935 Representation r = access_.representation(); |
5936 if (IsLoad()) { | 5936 if (IsLoad()) { |
5937 if (!info->access_.representation().IsCompatibleForLoad(r)) return false; | 5937 if (!info->access_.representation().IsCompatibleForLoad(r)) return false; |
5938 } else { | 5938 } else { |
5939 if (!info->access_.representation().IsCompatibleForStore(r)) return false; | 5939 if (!info->access_.representation().IsCompatibleForStore(r)) return false; |
5940 } | 5940 } |
5941 if (info->access_.offset() != access_.offset()) return false; | 5941 if (info->access_.offset() != access_.offset()) return false; |
5942 if (info->access_.IsInobject() != access_.IsInobject()) return false; | 5942 if (info->access_.IsInobject() != access_.IsInobject()) return false; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6015 // Clear any previously collected field maps/type. | 6015 // Clear any previously collected field maps/type. |
6016 field_maps_.Clear(); | 6016 field_maps_.Clear(); |
6017 field_type_ = HType::Tagged(); | 6017 field_type_ = HType::Tagged(); |
6018 | 6018 |
6019 // Figure out the field type from the accessor map. | 6019 // Figure out the field type from the accessor map. |
6020 Handle<HeapType> field_type(lookup_.GetFieldTypeFromMap(*map), isolate()); | 6020 Handle<HeapType> field_type(lookup_.GetFieldTypeFromMap(*map), isolate()); |
6021 | 6021 |
6022 // Collect the (stable) maps from the field type. | 6022 // Collect the (stable) maps from the field type. |
6023 int num_field_maps = field_type->NumClasses(); | 6023 int num_field_maps = field_type->NumClasses(); |
6024 if (num_field_maps == 0) return; | 6024 if (num_field_maps == 0) return; |
6025 ASSERT(access_.representation().IsHeapObject()); | 6025 DCHECK(access_.representation().IsHeapObject()); |
6026 field_maps_.Reserve(num_field_maps, zone()); | 6026 field_maps_.Reserve(num_field_maps, zone()); |
6027 HeapType::Iterator<Map> it = field_type->Classes(); | 6027 HeapType::Iterator<Map> it = field_type->Classes(); |
6028 while (!it.Done()) { | 6028 while (!it.Done()) { |
6029 Handle<Map> field_map = it.Current(); | 6029 Handle<Map> field_map = it.Current(); |
6030 if (!field_map->is_stable()) { | 6030 if (!field_map->is_stable()) { |
6031 field_maps_.Clear(); | 6031 field_maps_.Clear(); |
6032 return; | 6032 return; |
6033 } | 6033 } |
6034 field_maps_.Add(field_map, zone()); | 6034 field_maps_.Add(field_map, zone()); |
6035 it.Advance(); | 6035 it.Advance(); |
6036 } | 6036 } |
6037 field_maps_.Sort(); | 6037 field_maps_.Sort(); |
6038 ASSERT_EQ(num_field_maps, field_maps_.length()); | 6038 DCHECK_EQ(num_field_maps, field_maps_.length()); |
6039 | 6039 |
6040 // Determine field HType from field HeapType. | 6040 // Determine field HType from field HeapType. |
6041 field_type_ = HType::FromType<HeapType>(field_type); | 6041 field_type_ = HType::FromType<HeapType>(field_type); |
6042 ASSERT(field_type_.IsHeapObject()); | 6042 DCHECK(field_type_.IsHeapObject()); |
6043 | 6043 |
6044 // Add dependency on the map that introduced the field. | 6044 // Add dependency on the map that introduced the field. |
6045 Map::AddDependentCompilationInfo( | 6045 Map::AddDependentCompilationInfo( |
6046 handle(lookup_.GetFieldOwnerFromMap(*map), isolate()), | 6046 handle(lookup_.GetFieldOwnerFromMap(*map), isolate()), |
6047 DependentCode::kFieldTypeGroup, top_info()); | 6047 DependentCode::kFieldTypeGroup, top_info()); |
6048 } | 6048 } |
6049 | 6049 |
6050 | 6050 |
6051 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { | 6051 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { |
6052 Handle<Map> map = this->map(); | 6052 Handle<Map> map = this->map(); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6095 // Load field map for heap objects. | 6095 // Load field map for heap objects. |
6096 LoadFieldMaps(transition()); | 6096 LoadFieldMaps(transition()); |
6097 return true; | 6097 return true; |
6098 } | 6098 } |
6099 return false; | 6099 return false; |
6100 } | 6100 } |
6101 | 6101 |
6102 | 6102 |
6103 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic( | 6103 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic( |
6104 SmallMapList* types) { | 6104 SmallMapList* types) { |
6105 ASSERT(type_->Is(ToType(types->first()))); | 6105 DCHECK(type_->Is(ToType(types->first()))); |
6106 if (!CanAccessMonomorphic()) return false; | 6106 if (!CanAccessMonomorphic()) return false; |
6107 STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism); | 6107 STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism); |
6108 if (types->length() > kMaxLoadPolymorphism) return false; | 6108 if (types->length() > kMaxLoadPolymorphism) return false; |
6109 | 6109 |
6110 HObjectAccess access = HObjectAccess::ForMap(); // bogus default | 6110 HObjectAccess access = HObjectAccess::ForMap(); // bogus default |
6111 if (GetJSObjectFieldAccess(&access)) { | 6111 if (GetJSObjectFieldAccess(&access)) { |
6112 for (int i = 1; i < types->length(); ++i) { | 6112 for (int i = 1; i < types->length(); ++i) { |
6113 PropertyAccessInfo test_info( | 6113 PropertyAccessInfo test_info( |
6114 builder_, access_type_, ToType(types->at(i)), name_); | 6114 builder_, access_type_, ToType(types->at(i)), name_); |
6115 HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default | 6115 HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default |
6116 if (!test_info.GetJSObjectFieldAccess(&test_access)) return false; | 6116 if (!test_info.GetJSObjectFieldAccess(&test_access)) return false; |
6117 if (!access.Equals(test_access)) return false; | 6117 if (!access.Equals(test_access)) return false; |
6118 } | 6118 } |
6119 return true; | 6119 return true; |
6120 } | 6120 } |
6121 | 6121 |
6122 // Currently only handle Type::Number as a polymorphic case. | 6122 // Currently only handle Type::Number as a polymorphic case. |
6123 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber | 6123 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber |
6124 // instruction. | 6124 // instruction. |
6125 if (type_->Is(Type::Number())) return false; | 6125 if (type_->Is(Type::Number())) return false; |
6126 | 6126 |
6127 // Multiple maps cannot transition to the same target map. | 6127 // Multiple maps cannot transition to the same target map. |
6128 ASSERT(!IsLoad() || !lookup_.IsTransition()); | 6128 DCHECK(!IsLoad() || !lookup_.IsTransition()); |
6129 if (lookup_.IsTransition() && types->length() > 1) return false; | 6129 if (lookup_.IsTransition() && types->length() > 1) return false; |
6130 | 6130 |
6131 for (int i = 1; i < types->length(); ++i) { | 6131 for (int i = 1; i < types->length(); ++i) { |
6132 PropertyAccessInfo test_info( | 6132 PropertyAccessInfo test_info( |
6133 builder_, access_type_, ToType(types->at(i)), name_); | 6133 builder_, access_type_, ToType(types->at(i)), name_); |
6134 if (!test_info.IsCompatible(this)) return false; | 6134 if (!test_info.IsCompatible(this)) return false; |
6135 } | 6135 } |
6136 | 6136 |
6137 return true; | 6137 return true; |
6138 } | 6138 } |
(...skipping 18 matching lines...) Expand all Loading... |
6157 PropertyAccessInfo* info, | 6157 PropertyAccessInfo* info, |
6158 HValue* object, | 6158 HValue* object, |
6159 HValue* checked_object, | 6159 HValue* checked_object, |
6160 HValue* value, | 6160 HValue* value, |
6161 BailoutId ast_id, | 6161 BailoutId ast_id, |
6162 BailoutId return_id, | 6162 BailoutId return_id, |
6163 bool can_inline_accessor) { | 6163 bool can_inline_accessor) { |
6164 | 6164 |
6165 HObjectAccess access = HObjectAccess::ForMap(); // bogus default | 6165 HObjectAccess access = HObjectAccess::ForMap(); // bogus default |
6166 if (info->GetJSObjectFieldAccess(&access)) { | 6166 if (info->GetJSObjectFieldAccess(&access)) { |
6167 ASSERT(info->IsLoad()); | 6167 DCHECK(info->IsLoad()); |
6168 return New<HLoadNamedField>(object, checked_object, access); | 6168 return New<HLoadNamedField>(object, checked_object, access); |
6169 } | 6169 } |
6170 | 6170 |
6171 if (info->name().is_identical_to(isolate()->factory()->prototype_string()) && | 6171 if (info->name().is_identical_to(isolate()->factory()->prototype_string()) && |
6172 info->map()->function_with_prototype()) { | 6172 info->map()->function_with_prototype()) { |
6173 ASSERT(!info->map()->has_non_instance_prototype()); | 6173 DCHECK(!info->map()->has_non_instance_prototype()); |
6174 return New<HLoadFunctionPrototype>(checked_object); | 6174 return New<HLoadFunctionPrototype>(checked_object); |
6175 } | 6175 } |
6176 | 6176 |
6177 HValue* checked_holder = checked_object; | 6177 HValue* checked_holder = checked_object; |
6178 if (info->has_holder()) { | 6178 if (info->has_holder()) { |
6179 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype())); | 6179 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype())); |
6180 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); | 6180 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); |
6181 } | 6181 } |
6182 | 6182 |
6183 if (!info->lookup()->IsFound()) { | 6183 if (!info->lookup()->IsFound()) { |
6184 ASSERT(info->IsLoad()); | 6184 DCHECK(info->IsLoad()); |
6185 return graph()->GetConstantUndefined(); | 6185 return graph()->GetConstantUndefined(); |
6186 } | 6186 } |
6187 | 6187 |
6188 if (info->lookup()->IsField()) { | 6188 if (info->lookup()->IsField()) { |
6189 if (info->IsLoad()) { | 6189 if (info->IsLoad()) { |
6190 return BuildLoadNamedField(info, checked_holder); | 6190 return BuildLoadNamedField(info, checked_holder); |
6191 } else { | 6191 } else { |
6192 return BuildStoreNamedField(info, checked_object, value); | 6192 return BuildStoreNamedField(info, checked_object, value); |
6193 } | 6193 } |
6194 } | 6194 } |
6195 | 6195 |
6196 if (info->lookup()->IsTransition()) { | 6196 if (info->lookup()->IsTransition()) { |
6197 ASSERT(!info->IsLoad()); | 6197 DCHECK(!info->IsLoad()); |
6198 return BuildStoreNamedField(info, checked_object, value); | 6198 return BuildStoreNamedField(info, checked_object, value); |
6199 } | 6199 } |
6200 | 6200 |
6201 if (info->lookup()->IsPropertyCallbacks()) { | 6201 if (info->lookup()->IsPropertyCallbacks()) { |
6202 Push(checked_object); | 6202 Push(checked_object); |
6203 int argument_count = 1; | 6203 int argument_count = 1; |
6204 if (!info->IsLoad()) { | 6204 if (!info->IsLoad()) { |
6205 argument_count = 2; | 6205 argument_count = 2; |
6206 Push(value); | 6206 Push(value); |
6207 } | 6207 } |
6208 | 6208 |
6209 if (NeedsWrappingFor(info->type(), info->accessor())) { | 6209 if (NeedsWrappingFor(info->type(), info->accessor())) { |
6210 HValue* function = Add<HConstant>(info->accessor()); | 6210 HValue* function = Add<HConstant>(info->accessor()); |
6211 PushArgumentsFromEnvironment(argument_count); | 6211 PushArgumentsFromEnvironment(argument_count); |
6212 return New<HCallFunction>(function, argument_count, WRAP_AND_CALL); | 6212 return New<HCallFunction>(function, argument_count, WRAP_AND_CALL); |
6213 } else if (FLAG_inline_accessors && can_inline_accessor) { | 6213 } else if (FLAG_inline_accessors && can_inline_accessor) { |
6214 bool success = info->IsLoad() | 6214 bool success = info->IsLoad() |
6215 ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id) | 6215 ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id) |
6216 : TryInlineSetter( | 6216 : TryInlineSetter( |
6217 info->accessor(), info->map(), ast_id, return_id, value); | 6217 info->accessor(), info->map(), ast_id, return_id, value); |
6218 if (success || HasStackOverflow()) return NULL; | 6218 if (success || HasStackOverflow()) return NULL; |
6219 } | 6219 } |
6220 | 6220 |
6221 PushArgumentsFromEnvironment(argument_count); | 6221 PushArgumentsFromEnvironment(argument_count); |
6222 return BuildCallConstantFunction(info->accessor(), argument_count); | 6222 return BuildCallConstantFunction(info->accessor(), argument_count); |
6223 } | 6223 } |
6224 | 6224 |
6225 ASSERT(info->lookup()->IsConstant()); | 6225 DCHECK(info->lookup()->IsConstant()); |
6226 if (info->IsLoad()) { | 6226 if (info->IsLoad()) { |
6227 return New<HConstant>(info->constant()); | 6227 return New<HConstant>(info->constant()); |
6228 } else { | 6228 } else { |
6229 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); | 6229 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); |
6230 } | 6230 } |
6231 } | 6231 } |
6232 | 6232 |
6233 | 6233 |
6234 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess( | 6234 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess( |
6235 PropertyAccessType access_type, | 6235 PropertyAccessType access_type, |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6354 | 6354 |
6355 if (join != NULL) { | 6355 if (join != NULL) { |
6356 Goto(join); | 6356 Goto(join); |
6357 } else { | 6357 } else { |
6358 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6358 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
6359 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 6359 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
6360 return; | 6360 return; |
6361 } | 6361 } |
6362 } | 6362 } |
6363 | 6363 |
6364 ASSERT(join != NULL); | 6364 DCHECK(join != NULL); |
6365 if (join->HasPredecessor()) { | 6365 if (join->HasPredecessor()) { |
6366 join->SetJoinId(ast_id); | 6366 join->SetJoinId(ast_id); |
6367 set_current_block(join); | 6367 set_current_block(join); |
6368 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 6368 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
6369 } else { | 6369 } else { |
6370 set_current_block(NULL); | 6370 set_current_block(NULL); |
6371 } | 6371 } |
6372 } | 6372 } |
6373 | 6373 |
6374 | 6374 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6415 Add<HSimulate>(return_id, REMOVABLE_SIMULATE); | 6415 Add<HSimulate>(return_id, REMOVABLE_SIMULATE); |
6416 return ast_context()->ReturnValue(Pop()); | 6416 return ast_context()->ReturnValue(Pop()); |
6417 } | 6417 } |
6418 | 6418 |
6419 // Named store. | 6419 // Named store. |
6420 HValue* value = Pop(); | 6420 HValue* value = Pop(); |
6421 HValue* object = Pop(); | 6421 HValue* object = Pop(); |
6422 | 6422 |
6423 Literal* key = prop->key()->AsLiteral(); | 6423 Literal* key = prop->key()->AsLiteral(); |
6424 Handle<String> name = Handle<String>::cast(key->value()); | 6424 Handle<String> name = Handle<String>::cast(key->value()); |
6425 ASSERT(!name.is_null()); | 6425 DCHECK(!name.is_null()); |
6426 | 6426 |
6427 HInstruction* instr = BuildNamedAccess(STORE, ast_id, return_id, expr, | 6427 HInstruction* instr = BuildNamedAccess(STORE, ast_id, return_id, expr, |
6428 object, name, value, is_uninitialized); | 6428 object, name, value, is_uninitialized); |
6429 if (instr == NULL) return; | 6429 if (instr == NULL) return; |
6430 | 6430 |
6431 if (!ast_context()->IsEffect()) Push(value); | 6431 if (!ast_context()->IsEffect()) Push(value); |
6432 AddInstruction(instr); | 6432 AddInstruction(instr); |
6433 if (instr->HasObservableSideEffects()) { | 6433 if (instr->HasObservableSideEffects()) { |
6434 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6434 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
6435 } | 6435 } |
6436 if (!ast_context()->IsEffect()) Drop(1); | 6436 if (!ast_context()->IsEffect()) Drop(1); |
6437 return ast_context()->ReturnValue(value); | 6437 return ast_context()->ReturnValue(value); |
6438 } | 6438 } |
6439 | 6439 |
6440 | 6440 |
6441 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 6441 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
6442 Property* prop = expr->target()->AsProperty(); | 6442 Property* prop = expr->target()->AsProperty(); |
6443 ASSERT(prop != NULL); | 6443 DCHECK(prop != NULL); |
6444 CHECK_ALIVE(VisitForValue(prop->obj())); | 6444 CHECK_ALIVE(VisitForValue(prop->obj())); |
6445 if (!prop->key()->IsPropertyName()) { | 6445 if (!prop->key()->IsPropertyName()) { |
6446 CHECK_ALIVE(VisitForValue(prop->key())); | 6446 CHECK_ALIVE(VisitForValue(prop->key())); |
6447 } | 6447 } |
6448 CHECK_ALIVE(VisitForValue(expr->value())); | 6448 CHECK_ALIVE(VisitForValue(expr->value())); |
6449 BuildStore(expr, prop, expr->id(), | 6449 BuildStore(expr, prop, expr->id(), |
6450 expr->AssignmentId(), expr->IsUninitialized()); | 6450 expr->AssignmentId(), expr->IsUninitialized()); |
6451 } | 6451 } |
6452 | 6452 |
6453 | 6453 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6492 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6492 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
6493 } | 6493 } |
6494 } else { | 6494 } else { |
6495 HValue* global_object = Add<HLoadNamedField>( | 6495 HValue* global_object = Add<HLoadNamedField>( |
6496 context(), static_cast<HValue*>(NULL), | 6496 context(), static_cast<HValue*>(NULL), |
6497 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); | 6497 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); |
6498 HStoreNamedGeneric* instr = | 6498 HStoreNamedGeneric* instr = |
6499 Add<HStoreNamedGeneric>(global_object, var->name(), | 6499 Add<HStoreNamedGeneric>(global_object, var->name(), |
6500 value, function_strict_mode()); | 6500 value, function_strict_mode()); |
6501 USE(instr); | 6501 USE(instr); |
6502 ASSERT(instr->HasObservableSideEffects()); | 6502 DCHECK(instr->HasObservableSideEffects()); |
6503 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6503 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
6504 } | 6504 } |
6505 } | 6505 } |
6506 | 6506 |
6507 | 6507 |
6508 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 6508 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
6509 Expression* target = expr->target(); | 6509 Expression* target = expr->target(); |
6510 VariableProxy* proxy = target->AsVariableProxy(); | 6510 VariableProxy* proxy = target->AsVariableProxy(); |
6511 Property* prop = target->AsProperty(); | 6511 Property* prop = target->AsProperty(); |
6512 ASSERT(proxy == NULL || prop == NULL); | 6512 DCHECK(proxy == NULL || prop == NULL); |
6513 | 6513 |
6514 // We have a second position recorded in the FullCodeGenerator to have | 6514 // We have a second position recorded in the FullCodeGenerator to have |
6515 // type feedback for the binary operation. | 6515 // type feedback for the binary operation. |
6516 BinaryOperation* operation = expr->binary_operation(); | 6516 BinaryOperation* operation = expr->binary_operation(); |
6517 | 6517 |
6518 if (proxy != NULL) { | 6518 if (proxy != NULL) { |
6519 Variable* var = proxy->var(); | 6519 Variable* var = proxy->var(); |
6520 if (var->mode() == LET) { | 6520 if (var->mode() == LET) { |
6521 return Bailout(kUnsupportedLetCompoundAssignment); | 6521 return Bailout(kUnsupportedLetCompoundAssignment); |
6522 } | 6522 } |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6603 | 6603 |
6604 BuildStore(expr, prop, expr->id(), | 6604 BuildStore(expr, prop, expr->id(), |
6605 expr->AssignmentId(), expr->IsUninitialized()); | 6605 expr->AssignmentId(), expr->IsUninitialized()); |
6606 } else { | 6606 } else { |
6607 return Bailout(kInvalidLhsInCompoundAssignment); | 6607 return Bailout(kInvalidLhsInCompoundAssignment); |
6608 } | 6608 } |
6609 } | 6609 } |
6610 | 6610 |
6611 | 6611 |
6612 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { | 6612 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { |
6613 ASSERT(!HasStackOverflow()); | 6613 DCHECK(!HasStackOverflow()); |
6614 ASSERT(current_block() != NULL); | 6614 DCHECK(current_block() != NULL); |
6615 ASSERT(current_block()->HasPredecessor()); | 6615 DCHECK(current_block()->HasPredecessor()); |
6616 VariableProxy* proxy = expr->target()->AsVariableProxy(); | 6616 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
6617 Property* prop = expr->target()->AsProperty(); | 6617 Property* prop = expr->target()->AsProperty(); |
6618 ASSERT(proxy == NULL || prop == NULL); | 6618 DCHECK(proxy == NULL || prop == NULL); |
6619 | 6619 |
6620 if (expr->is_compound()) { | 6620 if (expr->is_compound()) { |
6621 HandleCompoundAssignment(expr); | 6621 HandleCompoundAssignment(expr); |
6622 return; | 6622 return; |
6623 } | 6623 } |
6624 | 6624 |
6625 if (prop != NULL) { | 6625 if (prop != NULL) { |
6626 HandlePropertyAssignment(expr); | 6626 HandlePropertyAssignment(expr); |
6627 } else if (proxy != NULL) { | 6627 } else if (proxy != NULL) { |
6628 Variable* var = proxy->var(); | 6628 Variable* var = proxy->var(); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6704 case CONST_LEGACY: | 6704 case CONST_LEGACY: |
6705 return ast_context()->ReturnValue(Pop()); | 6705 return ast_context()->ReturnValue(Pop()); |
6706 default: | 6706 default: |
6707 mode = HStoreContextSlot::kNoCheck; | 6707 mode = HStoreContextSlot::kNoCheck; |
6708 } | 6708 } |
6709 } else if (expr->op() == Token::INIT_VAR || | 6709 } else if (expr->op() == Token::INIT_VAR || |
6710 expr->op() == Token::INIT_LET || | 6710 expr->op() == Token::INIT_LET || |
6711 expr->op() == Token::INIT_CONST) { | 6711 expr->op() == Token::INIT_CONST) { |
6712 mode = HStoreContextSlot::kNoCheck; | 6712 mode = HStoreContextSlot::kNoCheck; |
6713 } else { | 6713 } else { |
6714 ASSERT(expr->op() == Token::INIT_CONST_LEGACY); | 6714 DCHECK(expr->op() == Token::INIT_CONST_LEGACY); |
6715 | 6715 |
6716 mode = HStoreContextSlot::kCheckIgnoreAssignment; | 6716 mode = HStoreContextSlot::kCheckIgnoreAssignment; |
6717 } | 6717 } |
6718 | 6718 |
6719 HValue* context = BuildContextChainWalk(var); | 6719 HValue* context = BuildContextChainWalk(var); |
6720 HStoreContextSlot* instr = Add<HStoreContextSlot>( | 6720 HStoreContextSlot* instr = Add<HStoreContextSlot>( |
6721 context, var->index(), mode, Top()); | 6721 context, var->index(), mode, Top()); |
6722 if (instr->HasObservableSideEffects()) { | 6722 if (instr->HasObservableSideEffects()) { |
6723 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); | 6723 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
6724 } | 6724 } |
6725 return ast_context()->ReturnValue(Pop()); | 6725 return ast_context()->ReturnValue(Pop()); |
6726 } | 6726 } |
6727 | 6727 |
6728 case Variable::LOOKUP: | 6728 case Variable::LOOKUP: |
6729 return Bailout(kAssignmentToLOOKUPVariable); | 6729 return Bailout(kAssignmentToLOOKUPVariable); |
6730 } | 6730 } |
6731 } else { | 6731 } else { |
6732 return Bailout(kInvalidLeftHandSideInAssignment); | 6732 return Bailout(kInvalidLeftHandSideInAssignment); |
6733 } | 6733 } |
6734 } | 6734 } |
6735 | 6735 |
6736 | 6736 |
6737 void HOptimizedGraphBuilder::VisitYield(Yield* expr) { | 6737 void HOptimizedGraphBuilder::VisitYield(Yield* expr) { |
6738 // Generators are not optimized, so we should never get here. | 6738 // Generators are not optimized, so we should never get here. |
6739 UNREACHABLE(); | 6739 UNREACHABLE(); |
6740 } | 6740 } |
6741 | 6741 |
6742 | 6742 |
6743 void HOptimizedGraphBuilder::VisitThrow(Throw* expr) { | 6743 void HOptimizedGraphBuilder::VisitThrow(Throw* expr) { |
6744 ASSERT(!HasStackOverflow()); | 6744 DCHECK(!HasStackOverflow()); |
6745 ASSERT(current_block() != NULL); | 6745 DCHECK(current_block() != NULL); |
6746 ASSERT(current_block()->HasPredecessor()); | 6746 DCHECK(current_block()->HasPredecessor()); |
6747 // We don't optimize functions with invalid left-hand sides in | 6747 // We don't optimize functions with invalid left-hand sides in |
6748 // assignments, count operations, or for-in. Consequently throw can | 6748 // assignments, count operations, or for-in. Consequently throw can |
6749 // currently only occur in an effect context. | 6749 // currently only occur in an effect context. |
6750 ASSERT(ast_context()->IsEffect()); | 6750 DCHECK(ast_context()->IsEffect()); |
6751 CHECK_ALIVE(VisitForValue(expr->exception())); | 6751 CHECK_ALIVE(VisitForValue(expr->exception())); |
6752 | 6752 |
6753 HValue* value = environment()->Pop(); | 6753 HValue* value = environment()->Pop(); |
6754 if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); | 6754 if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); |
6755 Add<HPushArguments>(value); | 6755 Add<HPushArguments>(value); |
6756 Add<HCallRuntime>(isolate()->factory()->empty_string(), | 6756 Add<HCallRuntime>(isolate()->factory()->empty_string(), |
6757 Runtime::FunctionForId(Runtime::kThrow), 1); | 6757 Runtime::FunctionForId(Runtime::kThrow), 1); |
6758 Add<HSimulate>(expr->id()); | 6758 Add<HSimulate>(expr->id()); |
6759 | 6759 |
6760 // If the throw definitely exits the function, we can finish with a dummy | 6760 // If the throw definitely exits the function, we can finish with a dummy |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6874 if (access_type == STORE && map->prototype()->IsJSObject()) { | 6874 if (access_type == STORE && map->prototype()->IsJSObject()) { |
6875 // monomorphic stores need a prototype chain check because shape | 6875 // monomorphic stores need a prototype chain check because shape |
6876 // changes could allow callbacks on elements in the chain that | 6876 // changes could allow callbacks on elements in the chain that |
6877 // aren't compatible with monomorphic keyed stores. | 6877 // aren't compatible with monomorphic keyed stores. |
6878 PrototypeIterator iter(map); | 6878 PrototypeIterator iter(map); |
6879 JSObject* holder = NULL; | 6879 JSObject* holder = NULL; |
6880 while (!iter.IsAtEnd()) { | 6880 while (!iter.IsAtEnd()) { |
6881 holder = JSObject::cast(*PrototypeIterator::GetCurrent(iter)); | 6881 holder = JSObject::cast(*PrototypeIterator::GetCurrent(iter)); |
6882 iter.Advance(); | 6882 iter.Advance(); |
6883 } | 6883 } |
6884 ASSERT(holder && holder->IsJSObject()); | 6884 DCHECK(holder && holder->IsJSObject()); |
6885 | 6885 |
6886 BuildCheckPrototypeMaps(handle(JSObject::cast(map->prototype())), | 6886 BuildCheckPrototypeMaps(handle(JSObject::cast(map->prototype())), |
6887 Handle<JSObject>(holder)); | 6887 Handle<JSObject>(holder)); |
6888 } | 6888 } |
6889 | 6889 |
6890 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); | 6890 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); |
6891 return BuildUncheckedMonomorphicElementAccess( | 6891 return BuildUncheckedMonomorphicElementAccess( |
6892 checked_object, key, val, | 6892 checked_object, key, val, |
6893 map->instance_type() == JS_ARRAY_TYPE, | 6893 map->instance_type() == JS_ARRAY_TYPE, |
6894 map->elements_kind(), access_type, | 6894 map->elements_kind(), access_type, |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7006 Handle<Map> map = maps->at(i); | 7006 Handle<Map> map = maps->at(i); |
7007 Handle<Map> transitioned_map = | 7007 Handle<Map> transitioned_map = |
7008 map->FindTransitionedMap(&possible_transitioned_maps); | 7008 map->FindTransitionedMap(&possible_transitioned_maps); |
7009 transition_target.Add(transitioned_map); | 7009 transition_target.Add(transitioned_map); |
7010 } | 7010 } |
7011 | 7011 |
7012 MapHandleList untransitionable_maps(maps->length()); | 7012 MapHandleList untransitionable_maps(maps->length()); |
7013 HTransitionElementsKind* transition = NULL; | 7013 HTransitionElementsKind* transition = NULL; |
7014 for (int i = 0; i < maps->length(); ++i) { | 7014 for (int i = 0; i < maps->length(); ++i) { |
7015 Handle<Map> map = maps->at(i); | 7015 Handle<Map> map = maps->at(i); |
7016 ASSERT(map->IsMap()); | 7016 DCHECK(map->IsMap()); |
7017 if (!transition_target.at(i).is_null()) { | 7017 if (!transition_target.at(i).is_null()) { |
7018 ASSERT(Map::IsValidElementsTransition( | 7018 DCHECK(Map::IsValidElementsTransition( |
7019 map->elements_kind(), | 7019 map->elements_kind(), |
7020 transition_target.at(i)->elements_kind())); | 7020 transition_target.at(i)->elements_kind())); |
7021 transition = Add<HTransitionElementsKind>(object, map, | 7021 transition = Add<HTransitionElementsKind>(object, map, |
7022 transition_target.at(i)); | 7022 transition_target.at(i)); |
7023 } else { | 7023 } else { |
7024 untransitionable_maps.Add(map); | 7024 untransitionable_maps.Add(map); |
7025 } | 7025 } |
7026 } | 7026 } |
7027 | 7027 |
7028 // If only one map is left after transitioning, handle this case | 7028 // If only one map is left after transitioning, handle this case |
7029 // monomorphically. | 7029 // monomorphically. |
7030 ASSERT(untransitionable_maps.length() >= 1); | 7030 DCHECK(untransitionable_maps.length() >= 1); |
7031 if (untransitionable_maps.length() == 1) { | 7031 if (untransitionable_maps.length() == 1) { |
7032 Handle<Map> untransitionable_map = untransitionable_maps[0]; | 7032 Handle<Map> untransitionable_map = untransitionable_maps[0]; |
7033 HInstruction* instr = NULL; | 7033 HInstruction* instr = NULL; |
7034 if (untransitionable_map->has_slow_elements_kind() || | 7034 if (untransitionable_map->has_slow_elements_kind() || |
7035 !untransitionable_map->IsJSObjectMap()) { | 7035 !untransitionable_map->IsJSObjectMap()) { |
7036 instr = AddInstruction(BuildKeyedGeneric(access_type, expr, object, key, | 7036 instr = AddInstruction(BuildKeyedGeneric(access_type, expr, object, key, |
7037 val)); | 7037 val)); |
7038 } else { | 7038 } else { |
7039 instr = BuildMonomorphicElementAccess( | 7039 instr = BuildMonomorphicElementAccess( |
7040 object, key, val, transition, untransitionable_map, access_type, | 7040 object, key, val, transition, untransitionable_map, access_type, |
(...skipping 14 matching lines...) Expand all Loading... |
7055 HCompareMap* mapcompare = | 7055 HCompareMap* mapcompare = |
7056 New<HCompareMap>(object, map, this_map, other_map); | 7056 New<HCompareMap>(object, map, this_map, other_map); |
7057 FinishCurrentBlock(mapcompare); | 7057 FinishCurrentBlock(mapcompare); |
7058 | 7058 |
7059 set_current_block(this_map); | 7059 set_current_block(this_map); |
7060 HInstruction* access = NULL; | 7060 HInstruction* access = NULL; |
7061 if (IsDictionaryElementsKind(elements_kind)) { | 7061 if (IsDictionaryElementsKind(elements_kind)) { |
7062 access = AddInstruction(BuildKeyedGeneric(access_type, expr, object, key, | 7062 access = AddInstruction(BuildKeyedGeneric(access_type, expr, object, key, |
7063 val)); | 7063 val)); |
7064 } else { | 7064 } else { |
7065 ASSERT(IsFastElementsKind(elements_kind) || | 7065 DCHECK(IsFastElementsKind(elements_kind) || |
7066 IsExternalArrayElementsKind(elements_kind) || | 7066 IsExternalArrayElementsKind(elements_kind) || |
7067 IsFixedTypedArrayElementsKind(elements_kind)); | 7067 IsFixedTypedArrayElementsKind(elements_kind)); |
7068 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); | 7068 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); |
7069 // Happily, mapcompare is a checked object. | 7069 // Happily, mapcompare is a checked object. |
7070 access = BuildUncheckedMonomorphicElementAccess( | 7070 access = BuildUncheckedMonomorphicElementAccess( |
7071 mapcompare, key, val, | 7071 mapcompare, key, val, |
7072 map->instance_type() == JS_ARRAY_TYPE, | 7072 map->instance_type() == JS_ARRAY_TYPE, |
7073 elements_kind, access_type, | 7073 elements_kind, access_type, |
7074 load_mode, | 7074 load_mode, |
7075 store_mode); | 7075 store_mode); |
7076 } | 7076 } |
7077 *has_side_effects |= access->HasObservableSideEffects(); | 7077 *has_side_effects |= access->HasObservableSideEffects(); |
7078 // The caller will use has_side_effects and add a correct Simulate. | 7078 // The caller will use has_side_effects and add a correct Simulate. |
7079 access->SetFlag(HValue::kHasNoObservableSideEffects); | 7079 access->SetFlag(HValue::kHasNoObservableSideEffects); |
7080 if (access_type == LOAD) { | 7080 if (access_type == LOAD) { |
7081 Push(access); | 7081 Push(access); |
7082 } | 7082 } |
7083 NoObservableSideEffectsScope scope(this); | 7083 NoObservableSideEffectsScope scope(this); |
7084 GotoNoSimulate(join); | 7084 GotoNoSimulate(join); |
7085 set_current_block(other_map); | 7085 set_current_block(other_map); |
7086 } | 7086 } |
7087 | 7087 |
7088 // Ensure that we visited at least one map above that goes to join. This is | 7088 // Ensure that we visited at least one map above that goes to join. This is |
7089 // necessary because FinishExitWithHardDeoptimization does an AbnormalExit | 7089 // necessary because FinishExitWithHardDeoptimization does an AbnormalExit |
7090 // rather than joining the join block. If this becomes an issue, insert a | 7090 // rather than joining the join block. If this becomes an issue, insert a |
7091 // generic access in the case length() == 0. | 7091 // generic access in the case length() == 0. |
7092 ASSERT(join->predecessors()->length() > 0); | 7092 DCHECK(join->predecessors()->length() > 0); |
7093 // Deopt if none of the cases matched. | 7093 // Deopt if none of the cases matched. |
7094 NoObservableSideEffectsScope scope(this); | 7094 NoObservableSideEffectsScope scope(this); |
7095 FinishExitWithHardDeoptimization("Unknown map in polymorphic element access"); | 7095 FinishExitWithHardDeoptimization("Unknown map in polymorphic element access"); |
7096 set_current_block(join); | 7096 set_current_block(join); |
7097 return access_type == STORE ? NULL : Pop(); | 7097 return access_type == STORE ? NULL : Pop(); |
7098 } | 7098 } |
7099 | 7099 |
7100 | 7100 |
7101 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( | 7101 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( |
7102 HValue* obj, | 7102 HValue* obj, |
7103 HValue* key, | 7103 HValue* key, |
7104 HValue* val, | 7104 HValue* val, |
7105 Expression* expr, | 7105 Expression* expr, |
7106 PropertyAccessType access_type, | 7106 PropertyAccessType access_type, |
7107 bool* has_side_effects) { | 7107 bool* has_side_effects) { |
7108 ASSERT(!expr->IsPropertyName()); | 7108 DCHECK(!expr->IsPropertyName()); |
7109 HInstruction* instr = NULL; | 7109 HInstruction* instr = NULL; |
7110 | 7110 |
7111 SmallMapList* types; | 7111 SmallMapList* types; |
7112 bool monomorphic = ComputeReceiverTypes(expr, obj, &types, zone()); | 7112 bool monomorphic = ComputeReceiverTypes(expr, obj, &types, zone()); |
7113 | 7113 |
7114 bool force_generic = false; | 7114 bool force_generic = false; |
7115 if (access_type == STORE && | 7115 if (access_type == STORE && |
7116 (monomorphic || (types != NULL && !types->is_empty()))) { | 7116 (monomorphic || (types != NULL && !types->is_empty()))) { |
7117 // Stores can't be mono/polymorphic if their prototype chain has dictionary | 7117 // Stores can't be mono/polymorphic if their prototype chain has dictionary |
7118 // elements. However a receiver map that has dictionary elements itself | 7118 // elements. However a receiver map that has dictionary elements itself |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7243 PropertyAccessType access, | 7243 PropertyAccessType access, |
7244 BailoutId ast_id, | 7244 BailoutId ast_id, |
7245 BailoutId return_id, | 7245 BailoutId return_id, |
7246 Expression* expr, | 7246 Expression* expr, |
7247 HValue* object, | 7247 HValue* object, |
7248 Handle<String> name, | 7248 Handle<String> name, |
7249 HValue* value, | 7249 HValue* value, |
7250 bool is_uninitialized) { | 7250 bool is_uninitialized) { |
7251 SmallMapList* types; | 7251 SmallMapList* types; |
7252 ComputeReceiverTypes(expr, object, &types, zone()); | 7252 ComputeReceiverTypes(expr, object, &types, zone()); |
7253 ASSERT(types != NULL); | 7253 DCHECK(types != NULL); |
7254 | 7254 |
7255 if (types->length() > 0) { | 7255 if (types->length() > 0) { |
7256 PropertyAccessInfo info(this, access, ToType(types->first()), name); | 7256 PropertyAccessInfo info(this, access, ToType(types->first()), name); |
7257 if (!info.CanAccessAsMonomorphic(types)) { | 7257 if (!info.CanAccessAsMonomorphic(types)) { |
7258 HandlePolymorphicNamedFieldAccess( | 7258 HandlePolymorphicNamedFieldAccess( |
7259 access, expr, ast_id, return_id, object, value, types, name); | 7259 access, expr, ast_id, return_id, object, value, types, name); |
7260 return NULL; | 7260 return NULL; |
7261 } | 7261 } |
7262 | 7262 |
7263 HValue* checked_object; | 7263 HValue* checked_object; |
7264 // Type::Number() is only supported by polymorphic load/call handling. | 7264 // Type::Number() is only supported by polymorphic load/call handling. |
7265 ASSERT(!info.type()->Is(Type::Number())); | 7265 DCHECK(!info.type()->Is(Type::Number())); |
7266 BuildCheckHeapObject(object); | 7266 BuildCheckHeapObject(object); |
7267 if (AreStringTypes(types)) { | 7267 if (AreStringTypes(types)) { |
7268 checked_object = | 7268 checked_object = |
7269 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); | 7269 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); |
7270 } else { | 7270 } else { |
7271 checked_object = Add<HCheckMaps>(object, types); | 7271 checked_object = Add<HCheckMaps>(object, types); |
7272 } | 7272 } |
7273 return BuildMonomorphicAccess( | 7273 return BuildMonomorphicAccess( |
7274 &info, object, checked_object, value, ast_id, return_id); | 7274 &info, object, checked_object, value, ast_id, return_id); |
7275 } | 7275 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7323 Drop(1); | 7323 Drop(1); |
7324 } | 7324 } |
7325 } | 7325 } |
7326 return ast_context()->ReturnValue(load); | 7326 return ast_context()->ReturnValue(load); |
7327 } | 7327 } |
7328 return ast_context()->ReturnInstruction(instr, ast_id); | 7328 return ast_context()->ReturnInstruction(instr, ast_id); |
7329 } | 7329 } |
7330 | 7330 |
7331 | 7331 |
7332 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { | 7332 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { |
7333 ASSERT(!HasStackOverflow()); | 7333 DCHECK(!HasStackOverflow()); |
7334 ASSERT(current_block() != NULL); | 7334 DCHECK(current_block() != NULL); |
7335 ASSERT(current_block()->HasPredecessor()); | 7335 DCHECK(current_block()->HasPredecessor()); |
7336 | 7336 |
7337 if (TryArgumentsAccess(expr)) return; | 7337 if (TryArgumentsAccess(expr)) return; |
7338 | 7338 |
7339 CHECK_ALIVE(VisitForValue(expr->obj())); | 7339 CHECK_ALIVE(VisitForValue(expr->obj())); |
7340 if (!expr->key()->IsPropertyName() || expr->IsStringAccess()) { | 7340 if (!expr->key()->IsPropertyName() || expr->IsStringAccess()) { |
7341 CHECK_ALIVE(VisitForValue(expr->key())); | 7341 CHECK_ALIVE(VisitForValue(expr->key())); |
7342 } | 7342 } |
7343 | 7343 |
7344 BuildLoad(expr, expr->id()); | 7344 BuildLoad(expr, expr->id()); |
7345 } | 7345 } |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7620 if (!ast_context()->IsEffect()) Push(call); | 7620 if (!ast_context()->IsEffect()) Push(call); |
7621 Goto(join); | 7621 Goto(join); |
7622 } else { | 7622 } else { |
7623 return ast_context()->ReturnInstruction(call, expr->id()); | 7623 return ast_context()->ReturnInstruction(call, expr->id()); |
7624 } | 7624 } |
7625 } | 7625 } |
7626 | 7626 |
7627 // We assume that control flow is always live after an expression. So | 7627 // We assume that control flow is always live after an expression. So |
7628 // even without predecessors to the join block, we set it as the exit | 7628 // even without predecessors to the join block, we set it as the exit |
7629 // block and continue by adding instructions there. | 7629 // block and continue by adding instructions there. |
7630 ASSERT(join != NULL); | 7630 DCHECK(join != NULL); |
7631 if (join->HasPredecessor()) { | 7631 if (join->HasPredecessor()) { |
7632 set_current_block(join); | 7632 set_current_block(join); |
7633 join->SetJoinId(expr->id()); | 7633 join->SetJoinId(expr->id()); |
7634 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); | 7634 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); |
7635 } else { | 7635 } else { |
7636 set_current_block(NULL); | 7636 set_current_block(NULL); |
7637 } | 7637 } |
7638 } | 7638 } |
7639 | 7639 |
7640 | 7640 |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7832 Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG, | 7832 Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG, |
7833 &target_info, | 7833 &target_info, |
7834 target_shared); | 7834 target_shared); |
7835 } | 7835 } |
7836 | 7836 |
7837 // ---------------------------------------------------------------- | 7837 // ---------------------------------------------------------------- |
7838 // After this point, we've made a decision to inline this function (so | 7838 // After this point, we've made a decision to inline this function (so |
7839 // TryInline should always return true). | 7839 // TryInline should always return true). |
7840 | 7840 |
7841 // Type-check the inlined function. | 7841 // Type-check the inlined function. |
7842 ASSERT(target_shared->has_deoptimization_support()); | 7842 DCHECK(target_shared->has_deoptimization_support()); |
7843 AstTyper::Run(&target_info); | 7843 AstTyper::Run(&target_info); |
7844 | 7844 |
7845 int function_id = graph()->TraceInlinedFunction(target_shared, position); | 7845 int function_id = graph()->TraceInlinedFunction(target_shared, position); |
7846 | 7846 |
7847 // Save the pending call context. Set up new one for the inlined function. | 7847 // Save the pending call context. Set up new one for the inlined function. |
7848 // The function state is new-allocated because we need to delete it | 7848 // The function state is new-allocated because we need to delete it |
7849 // in two different places. | 7849 // in two different places. |
7850 FunctionState* target_state = new FunctionState( | 7850 FunctionState* target_state = new FunctionState( |
7851 this, &target_info, inlining_kind, function_id); | 7851 this, &target_info, inlining_kind, function_id); |
7852 | 7852 |
(...skipping 13 matching lines...) Expand all Loading... |
7866 // current arguments values to use them for materialization. | 7866 // current arguments values to use them for materialization. |
7867 HEnvironment* arguments_env = inner_env->arguments_environment(); | 7867 HEnvironment* arguments_env = inner_env->arguments_environment(); |
7868 int parameter_count = arguments_env->parameter_count(); | 7868 int parameter_count = arguments_env->parameter_count(); |
7869 HArgumentsObject* arguments_object = Add<HArgumentsObject>(parameter_count); | 7869 HArgumentsObject* arguments_object = Add<HArgumentsObject>(parameter_count); |
7870 for (int i = 0; i < parameter_count; i++) { | 7870 for (int i = 0; i < parameter_count; i++) { |
7871 arguments_object->AddArgument(arguments_env->Lookup(i), zone()); | 7871 arguments_object->AddArgument(arguments_env->Lookup(i), zone()); |
7872 } | 7872 } |
7873 | 7873 |
7874 // If the function uses arguments object then bind bind one. | 7874 // If the function uses arguments object then bind bind one. |
7875 if (function->scope()->arguments() != NULL) { | 7875 if (function->scope()->arguments() != NULL) { |
7876 ASSERT(function->scope()->arguments()->IsStackAllocated()); | 7876 DCHECK(function->scope()->arguments()->IsStackAllocated()); |
7877 inner_env->Bind(function->scope()->arguments(), arguments_object); | 7877 inner_env->Bind(function->scope()->arguments(), arguments_object); |
7878 } | 7878 } |
7879 | 7879 |
7880 // Capture the state before invoking the inlined function for deopt in the | 7880 // Capture the state before invoking the inlined function for deopt in the |
7881 // inlined function. This simulate has no bailout-id since it's not directly | 7881 // inlined function. This simulate has no bailout-id since it's not directly |
7882 // reachable for deopt, and is only used to capture the state. If the simulate | 7882 // reachable for deopt, and is only used to capture the state. If the simulate |
7883 // becomes reachable by merging, the ast id of the simulate merged into it is | 7883 // becomes reachable by merging, the ast id of the simulate merged into it is |
7884 // adopted. | 7884 // adopted. |
7885 Add<HSimulate>(BailoutId::None()); | 7885 Add<HSimulate>(BailoutId::None()); |
7886 | 7886 |
(...skipping 17 matching lines...) Expand all Loading... |
7904 target_shared->DisableOptimization(kInliningBailedOut); | 7904 target_shared->DisableOptimization(kInliningBailedOut); |
7905 inline_bailout_ = true; | 7905 inline_bailout_ = true; |
7906 delete target_state; | 7906 delete target_state; |
7907 return true; | 7907 return true; |
7908 } | 7908 } |
7909 | 7909 |
7910 // Update inlined nodes count. | 7910 // Update inlined nodes count. |
7911 inlined_count_ += nodes_added; | 7911 inlined_count_ += nodes_added; |
7912 | 7912 |
7913 Handle<Code> unoptimized_code(target_shared->code()); | 7913 Handle<Code> unoptimized_code(target_shared->code()); |
7914 ASSERT(unoptimized_code->kind() == Code::FUNCTION); | 7914 DCHECK(unoptimized_code->kind() == Code::FUNCTION); |
7915 Handle<TypeFeedbackInfo> type_info( | 7915 Handle<TypeFeedbackInfo> type_info( |
7916 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); | 7916 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); |
7917 graph()->update_type_change_checksum(type_info->own_type_change_checksum()); | 7917 graph()->update_type_change_checksum(type_info->own_type_change_checksum()); |
7918 | 7918 |
7919 TraceInline(target, caller, NULL); | 7919 TraceInline(target, caller, NULL); |
7920 | 7920 |
7921 if (current_block() != NULL) { | 7921 if (current_block() != NULL) { |
7922 FunctionState* state = function_state(); | 7922 FunctionState* state = function_state(); |
7923 if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { | 7923 if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { |
7924 // Falling off the end of an inlined construct call. In a test context the | 7924 // Falling off the end of an inlined construct call. In a test context the |
7925 // return value will always evaluate to true, in a value context the | 7925 // return value will always evaluate to true, in a value context the |
7926 // return value is the newly allocated receiver. | 7926 // return value is the newly allocated receiver. |
7927 if (call_context()->IsTest()) { | 7927 if (call_context()->IsTest()) { |
7928 Goto(inlined_test_context()->if_true(), state); | 7928 Goto(inlined_test_context()->if_true(), state); |
7929 } else if (call_context()->IsEffect()) { | 7929 } else if (call_context()->IsEffect()) { |
7930 Goto(function_return(), state); | 7930 Goto(function_return(), state); |
7931 } else { | 7931 } else { |
7932 ASSERT(call_context()->IsValue()); | 7932 DCHECK(call_context()->IsValue()); |
7933 AddLeaveInlined(implicit_return_value, state); | 7933 AddLeaveInlined(implicit_return_value, state); |
7934 } | 7934 } |
7935 } else if (state->inlining_kind() == SETTER_CALL_RETURN) { | 7935 } else if (state->inlining_kind() == SETTER_CALL_RETURN) { |
7936 // Falling off the end of an inlined setter call. The returned value is | 7936 // Falling off the end of an inlined setter call. The returned value is |
7937 // never used, the value of an assignment is always the value of the RHS | 7937 // never used, the value of an assignment is always the value of the RHS |
7938 // of the assignment. | 7938 // of the assignment. |
7939 if (call_context()->IsTest()) { | 7939 if (call_context()->IsTest()) { |
7940 inlined_test_context()->ReturnValue(implicit_return_value); | 7940 inlined_test_context()->ReturnValue(implicit_return_value); |
7941 } else if (call_context()->IsEffect()) { | 7941 } else if (call_context()->IsEffect()) { |
7942 Goto(function_return(), state); | 7942 Goto(function_return(), state); |
7943 } else { | 7943 } else { |
7944 ASSERT(call_context()->IsValue()); | 7944 DCHECK(call_context()->IsValue()); |
7945 AddLeaveInlined(implicit_return_value, state); | 7945 AddLeaveInlined(implicit_return_value, state); |
7946 } | 7946 } |
7947 } else { | 7947 } else { |
7948 // Falling off the end of a normal inlined function. This basically means | 7948 // Falling off the end of a normal inlined function. This basically means |
7949 // returning undefined. | 7949 // returning undefined. |
7950 if (call_context()->IsTest()) { | 7950 if (call_context()->IsTest()) { |
7951 Goto(inlined_test_context()->if_false(), state); | 7951 Goto(inlined_test_context()->if_false(), state); |
7952 } else if (call_context()->IsEffect()) { | 7952 } else if (call_context()->IsEffect()) { |
7953 Goto(function_return(), state); | 7953 Goto(function_return(), state); |
7954 } else { | 7954 } else { |
7955 ASSERT(call_context()->IsValue()); | 7955 DCHECK(call_context()->IsValue()); |
7956 AddLeaveInlined(undefined, state); | 7956 AddLeaveInlined(undefined, state); |
7957 } | 7957 } |
7958 } | 7958 } |
7959 } | 7959 } |
7960 | 7960 |
7961 // Fix up the function exits. | 7961 // Fix up the function exits. |
7962 if (inlined_test_context() != NULL) { | 7962 if (inlined_test_context() != NULL) { |
7963 HBasicBlock* if_true = inlined_test_context()->if_true(); | 7963 HBasicBlock* if_true = inlined_test_context()->if_true(); |
7964 HBasicBlock* if_false = inlined_test_context()->if_false(); | 7964 HBasicBlock* if_false = inlined_test_context()->if_false(); |
7965 | 7965 |
7966 HEnterInlined* entry = function_state()->entry(); | 7966 HEnterInlined* entry = function_state()->entry(); |
7967 | 7967 |
7968 // Pop the return test context from the expression context stack. | 7968 // Pop the return test context from the expression context stack. |
7969 ASSERT(ast_context() == inlined_test_context()); | 7969 DCHECK(ast_context() == inlined_test_context()); |
7970 ClearInlinedTestContext(); | 7970 ClearInlinedTestContext(); |
7971 delete target_state; | 7971 delete target_state; |
7972 | 7972 |
7973 // Forward to the real test context. | 7973 // Forward to the real test context. |
7974 if (if_true->HasPredecessor()) { | 7974 if (if_true->HasPredecessor()) { |
7975 entry->RegisterReturnTarget(if_true, zone()); | 7975 entry->RegisterReturnTarget(if_true, zone()); |
7976 if_true->SetJoinId(ast_id); | 7976 if_true->SetJoinId(ast_id); |
7977 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); | 7977 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); |
7978 Goto(if_true, true_target, function_state()); | 7978 Goto(if_true, true_target, function_state()); |
7979 } | 7979 } |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8168 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { | 8168 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { |
8169 double exponent = HConstant::cast(right)->DoubleValue(); | 8169 double exponent = HConstant::cast(right)->DoubleValue(); |
8170 if (exponent == 0.5) { | 8170 if (exponent == 0.5) { |
8171 result = NewUncasted<HUnaryMathOperation>(left, kMathPowHalf); | 8171 result = NewUncasted<HUnaryMathOperation>(left, kMathPowHalf); |
8172 } else if (exponent == -0.5) { | 8172 } else if (exponent == -0.5) { |
8173 HValue* one = graph()->GetConstant1(); | 8173 HValue* one = graph()->GetConstant1(); |
8174 HInstruction* sqrt = AddUncasted<HUnaryMathOperation>( | 8174 HInstruction* sqrt = AddUncasted<HUnaryMathOperation>( |
8175 left, kMathPowHalf); | 8175 left, kMathPowHalf); |
8176 // MathPowHalf doesn't have side effects so there's no need for | 8176 // MathPowHalf doesn't have side effects so there's no need for |
8177 // an environment simulation here. | 8177 // an environment simulation here. |
8178 ASSERT(!sqrt->HasObservableSideEffects()); | 8178 DCHECK(!sqrt->HasObservableSideEffects()); |
8179 result = NewUncasted<HDiv>(one, sqrt); | 8179 result = NewUncasted<HDiv>(one, sqrt); |
8180 } else if (exponent == 2.0) { | 8180 } else if (exponent == 2.0) { |
8181 result = NewUncasted<HMul>(left, left); | 8181 result = NewUncasted<HMul>(left, left); |
8182 } | 8182 } |
8183 } | 8183 } |
8184 | 8184 |
8185 if (result == NULL) { | 8185 if (result == NULL) { |
8186 result = NewUncasted<HPower>(left, right); | 8186 result = NewUncasted<HPower>(left, right); |
8187 } | 8187 } |
8188 ast_context()->ReturnInstruction(result, expr->id()); | 8188 ast_context()->ReturnInstruction(result, expr->id()); |
(...skipping 22 matching lines...) Expand all Loading... |
8211 ast_context()->ReturnInstruction(result, expr->id()); | 8211 ast_context()->ReturnInstruction(result, expr->id()); |
8212 return true; | 8212 return true; |
8213 } | 8213 } |
8214 break; | 8214 break; |
8215 case kArrayPop: { | 8215 case kArrayPop: { |
8216 if (receiver_map.is_null()) return false; | 8216 if (receiver_map.is_null()) return false; |
8217 if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false; | 8217 if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false; |
8218 ElementsKind elements_kind = receiver_map->elements_kind(); | 8218 ElementsKind elements_kind = receiver_map->elements_kind(); |
8219 if (!IsFastElementsKind(elements_kind)) return false; | 8219 if (!IsFastElementsKind(elements_kind)) return false; |
8220 if (receiver_map->is_observed()) return false; | 8220 if (receiver_map->is_observed()) return false; |
8221 ASSERT(receiver_map->is_extensible()); | 8221 DCHECK(receiver_map->is_extensible()); |
8222 | 8222 |
8223 Drop(expr->arguments()->length()); | 8223 Drop(expr->arguments()->length()); |
8224 HValue* result; | 8224 HValue* result; |
8225 HValue* reduced_length; | 8225 HValue* reduced_length; |
8226 HValue* receiver = Pop(); | 8226 HValue* receiver = Pop(); |
8227 | 8227 |
8228 HValue* checked_object = AddCheckMap(receiver, receiver_map); | 8228 HValue* checked_object = AddCheckMap(receiver, receiver_map); |
8229 HValue* length = Add<HLoadNamedField>( | 8229 HValue* length = Add<HLoadNamedField>( |
8230 checked_object, static_cast<HValue*>(NULL), | 8230 checked_object, static_cast<HValue*>(NULL), |
8231 HObjectAccess::ForArrayLength(elements_kind)); | 8231 HObjectAccess::ForArrayLength(elements_kind)); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8276 ast_context()->ReturnValue(result); | 8276 ast_context()->ReturnValue(result); |
8277 return true; | 8277 return true; |
8278 } | 8278 } |
8279 case kArrayPush: { | 8279 case kArrayPush: { |
8280 if (receiver_map.is_null()) return false; | 8280 if (receiver_map.is_null()) return false; |
8281 if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false; | 8281 if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false; |
8282 ElementsKind elements_kind = receiver_map->elements_kind(); | 8282 ElementsKind elements_kind = receiver_map->elements_kind(); |
8283 if (!IsFastElementsKind(elements_kind)) return false; | 8283 if (!IsFastElementsKind(elements_kind)) return false; |
8284 if (receiver_map->is_observed()) return false; | 8284 if (receiver_map->is_observed()) return false; |
8285 if (JSArray::IsReadOnlyLengthDescriptor(receiver_map)) return false; | 8285 if (JSArray::IsReadOnlyLengthDescriptor(receiver_map)) return false; |
8286 ASSERT(receiver_map->is_extensible()); | 8286 DCHECK(receiver_map->is_extensible()); |
8287 | 8287 |
8288 // If there may be elements accessors in the prototype chain, the fast | 8288 // If there may be elements accessors in the prototype chain, the fast |
8289 // inlined version can't be used. | 8289 // inlined version can't be used. |
8290 if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false; | 8290 if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false; |
8291 // If there currently can be no elements accessors on the prototype chain, | 8291 // If there currently can be no elements accessors on the prototype chain, |
8292 // it doesn't mean that there won't be any later. Install a full prototype | 8292 // it doesn't mean that there won't be any later. Install a full prototype |
8293 // chain check to trap element accessors being installed on the prototype | 8293 // chain check to trap element accessors being installed on the prototype |
8294 // chain, which would cause elements to go to dictionary mode and result | 8294 // chain, which would cause elements to go to dictionary mode and result |
8295 // in a map change. | 8295 // in a map change. |
8296 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); | 8296 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8328 | 8328 |
8329 ast_context()->ReturnValue(new_size); | 8329 ast_context()->ReturnValue(new_size); |
8330 return true; | 8330 return true; |
8331 } | 8331 } |
8332 case kArrayShift: { | 8332 case kArrayShift: { |
8333 if (receiver_map.is_null()) return false; | 8333 if (receiver_map.is_null()) return false; |
8334 if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false; | 8334 if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false; |
8335 ElementsKind kind = receiver_map->elements_kind(); | 8335 ElementsKind kind = receiver_map->elements_kind(); |
8336 if (!IsFastElementsKind(kind)) return false; | 8336 if (!IsFastElementsKind(kind)) return false; |
8337 if (receiver_map->is_observed()) return false; | 8337 if (receiver_map->is_observed()) return false; |
8338 ASSERT(receiver_map->is_extensible()); | 8338 DCHECK(receiver_map->is_extensible()); |
8339 | 8339 |
8340 // If there may be elements accessors in the prototype chain, the fast | 8340 // If there may be elements accessors in the prototype chain, the fast |
8341 // inlined version can't be used. | 8341 // inlined version can't be used. |
8342 if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false; | 8342 if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false; |
8343 | 8343 |
8344 // If there currently can be no elements accessors on the prototype chain, | 8344 // If there currently can be no elements accessors on the prototype chain, |
8345 // it doesn't mean that there won't be any later. Install a full prototype | 8345 // it doesn't mean that there won't be any later. Install a full prototype |
8346 // chain check to trap element accessors being installed on the prototype | 8346 // chain check to trap element accessors being installed on the prototype |
8347 // chain, which would cause elements to go to dictionary mode and result | 8347 // chain, which would cause elements to go to dictionary mode and result |
8348 // in a map change. | 8348 // in a map change. |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8443 return true; | 8443 return true; |
8444 } | 8444 } |
8445 case kArrayIndexOf: | 8445 case kArrayIndexOf: |
8446 case kArrayLastIndexOf: { | 8446 case kArrayLastIndexOf: { |
8447 if (receiver_map.is_null()) return false; | 8447 if (receiver_map.is_null()) return false; |
8448 if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false; | 8448 if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false; |
8449 ElementsKind kind = receiver_map->elements_kind(); | 8449 ElementsKind kind = receiver_map->elements_kind(); |
8450 if (!IsFastElementsKind(kind)) return false; | 8450 if (!IsFastElementsKind(kind)) return false; |
8451 if (receiver_map->is_observed()) return false; | 8451 if (receiver_map->is_observed()) return false; |
8452 if (argument_count != 2) return false; | 8452 if (argument_count != 2) return false; |
8453 ASSERT(receiver_map->is_extensible()); | 8453 DCHECK(receiver_map->is_extensible()); |
8454 | 8454 |
8455 // If there may be elements accessors in the prototype chain, the fast | 8455 // If there may be elements accessors in the prototype chain, the fast |
8456 // inlined version can't be used. | 8456 // inlined version can't be used. |
8457 if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false; | 8457 if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false; |
8458 | 8458 |
8459 // If there currently can be no elements accessors on the prototype chain, | 8459 // If there currently can be no elements accessors on the prototype chain, |
8460 // it doesn't mean that there won't be any later. Install a full prototype | 8460 // it doesn't mean that there won't be any later. Install a full prototype |
8461 // chain check to trap element accessors being installed on the prototype | 8461 // chain check to trap element accessors being installed on the prototype |
8462 // chain, which would cause elements to go to dictionary mode and result | 8462 // chain, which would cause elements to go to dictionary mode and result |
8463 // in a map change. | 8463 // in a map change. |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8550 int argc, | 8550 int argc, |
8551 BailoutId ast_id, | 8551 BailoutId ast_id, |
8552 ApiCallType call_type) { | 8552 ApiCallType call_type) { |
8553 CallOptimization optimization(function); | 8553 CallOptimization optimization(function); |
8554 if (!optimization.is_simple_api_call()) return false; | 8554 if (!optimization.is_simple_api_call()) return false; |
8555 Handle<Map> holder_map; | 8555 Handle<Map> holder_map; |
8556 if (call_type == kCallApiFunction) { | 8556 if (call_type == kCallApiFunction) { |
8557 // Cannot embed a direct reference to the global proxy map | 8557 // Cannot embed a direct reference to the global proxy map |
8558 // as it maybe dropped on deserialization. | 8558 // as it maybe dropped on deserialization. |
8559 CHECK(!isolate()->serializer_enabled()); | 8559 CHECK(!isolate()->serializer_enabled()); |
8560 ASSERT_EQ(0, receiver_maps->length()); | 8560 DCHECK_EQ(0, receiver_maps->length()); |
8561 receiver_maps->Add(handle(function->global_proxy()->map()), zone()); | 8561 receiver_maps->Add(handle(function->global_proxy()->map()), zone()); |
8562 } | 8562 } |
8563 CallOptimization::HolderLookup holder_lookup = | 8563 CallOptimization::HolderLookup holder_lookup = |
8564 CallOptimization::kHolderNotFound; | 8564 CallOptimization::kHolderNotFound; |
8565 Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType( | 8565 Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType( |
8566 receiver_maps->first(), &holder_lookup); | 8566 receiver_maps->first(), &holder_lookup); |
8567 if (holder_lookup == CallOptimization::kHolderNotFound) return false; | 8567 if (holder_lookup == CallOptimization::kHolderNotFound) return false; |
8568 | 8568 |
8569 if (FLAG_trace_inlining) { | 8569 if (FLAG_trace_inlining) { |
8570 PrintF("Inlining api function "); | 8570 PrintF("Inlining api function "); |
8571 function->ShortPrint(); | 8571 function->ShortPrint(); |
8572 PrintF("\n"); | 8572 PrintF("\n"); |
8573 } | 8573 } |
8574 | 8574 |
8575 bool drop_extra = false; | 8575 bool drop_extra = false; |
8576 bool is_store = false; | 8576 bool is_store = false; |
8577 switch (call_type) { | 8577 switch (call_type) { |
8578 case kCallApiFunction: | 8578 case kCallApiFunction: |
8579 case kCallApiMethod: | 8579 case kCallApiMethod: |
8580 // Need to check that none of the receiver maps could have changed. | 8580 // Need to check that none of the receiver maps could have changed. |
8581 Add<HCheckMaps>(receiver, receiver_maps); | 8581 Add<HCheckMaps>(receiver, receiver_maps); |
8582 // Need to ensure the chain between receiver and api_holder is intact. | 8582 // Need to ensure the chain between receiver and api_holder is intact. |
8583 if (holder_lookup == CallOptimization::kHolderFound) { | 8583 if (holder_lookup == CallOptimization::kHolderFound) { |
8584 AddCheckPrototypeMaps(api_holder, receiver_maps->first()); | 8584 AddCheckPrototypeMaps(api_holder, receiver_maps->first()); |
8585 } else { | 8585 } else { |
8586 ASSERT_EQ(holder_lookup, CallOptimization::kHolderIsReceiver); | 8586 DCHECK_EQ(holder_lookup, CallOptimization::kHolderIsReceiver); |
8587 } | 8587 } |
8588 // Includes receiver. | 8588 // Includes receiver. |
8589 PushArgumentsFromEnvironment(argc + 1); | 8589 PushArgumentsFromEnvironment(argc + 1); |
8590 // Drop function after call. | 8590 // Drop function after call. |
8591 drop_extra = true; | 8591 drop_extra = true; |
8592 break; | 8592 break; |
8593 case kCallApiGetter: | 8593 case kCallApiGetter: |
8594 // Receiver and prototype chain cannot have changed. | 8594 // Receiver and prototype chain cannot have changed. |
8595 ASSERT_EQ(0, argc); | 8595 DCHECK_EQ(0, argc); |
8596 ASSERT_EQ(NULL, receiver); | 8596 DCHECK_EQ(NULL, receiver); |
8597 // Receiver is on expression stack. | 8597 // Receiver is on expression stack. |
8598 receiver = Pop(); | 8598 receiver = Pop(); |
8599 Add<HPushArguments>(receiver); | 8599 Add<HPushArguments>(receiver); |
8600 break; | 8600 break; |
8601 case kCallApiSetter: | 8601 case kCallApiSetter: |
8602 { | 8602 { |
8603 is_store = true; | 8603 is_store = true; |
8604 // Receiver and prototype chain cannot have changed. | 8604 // Receiver and prototype chain cannot have changed. |
8605 ASSERT_EQ(1, argc); | 8605 DCHECK_EQ(1, argc); |
8606 ASSERT_EQ(NULL, receiver); | 8606 DCHECK_EQ(NULL, receiver); |
8607 // Receiver and value are on expression stack. | 8607 // Receiver and value are on expression stack. |
8608 HValue* value = Pop(); | 8608 HValue* value = Pop(); |
8609 receiver = Pop(); | 8609 receiver = Pop(); |
8610 Add<HPushArguments>(receiver, value); | 8610 Add<HPushArguments>(receiver, value); |
8611 break; | 8611 break; |
8612 } | 8612 } |
8613 } | 8613 } |
8614 | 8614 |
8615 HValue* holder = NULL; | 8615 HValue* holder = NULL; |
8616 switch (holder_lookup) { | 8616 switch (holder_lookup) { |
(...skipping 25 matching lines...) Expand all Loading... |
8642 api_function_address | 8642 api_function_address |
8643 }; | 8643 }; |
8644 | 8644 |
8645 CallInterfaceDescriptor* descriptor = | 8645 CallInterfaceDescriptor* descriptor = |
8646 isolate()->call_descriptor(Isolate::ApiFunctionCall); | 8646 isolate()->call_descriptor(Isolate::ApiFunctionCall); |
8647 | 8647 |
8648 CallApiFunctionStub stub(isolate(), is_store, call_data_is_undefined, argc); | 8648 CallApiFunctionStub stub(isolate(), is_store, call_data_is_undefined, argc); |
8649 Handle<Code> code = stub.GetCode(); | 8649 Handle<Code> code = stub.GetCode(); |
8650 HConstant* code_value = Add<HConstant>(code); | 8650 HConstant* code_value = Add<HConstant>(code); |
8651 | 8651 |
8652 ASSERT((sizeof(op_vals) / kPointerSize) == | 8652 DCHECK((sizeof(op_vals) / kPointerSize) == |
8653 descriptor->GetEnvironmentLength()); | 8653 descriptor->GetEnvironmentLength()); |
8654 | 8654 |
8655 HInstruction* call = New<HCallWithDescriptor>( | 8655 HInstruction* call = New<HCallWithDescriptor>( |
8656 code_value, argc + 1, descriptor, | 8656 code_value, argc + 1, descriptor, |
8657 Vector<HValue*>(op_vals, descriptor->GetEnvironmentLength())); | 8657 Vector<HValue*>(op_vals, descriptor->GetEnvironmentLength())); |
8658 | 8658 |
8659 if (drop_extra) Drop(1); // Drop function. | 8659 if (drop_extra) Drop(1); // Drop function. |
8660 ast_context()->ReturnInstruction(call, ast_id); | 8660 ast_context()->ReturnInstruction(call, ast_id); |
8661 return true; | 8661 return true; |
8662 } | 8662 } |
8663 | 8663 |
8664 | 8664 |
8665 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) { | 8665 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) { |
8666 ASSERT(expr->expression()->IsProperty()); | 8666 DCHECK(expr->expression()->IsProperty()); |
8667 | 8667 |
8668 if (!expr->IsMonomorphic()) { | 8668 if (!expr->IsMonomorphic()) { |
8669 return false; | 8669 return false; |
8670 } | 8670 } |
8671 Handle<Map> function_map = expr->GetReceiverTypes()->first(); | 8671 Handle<Map> function_map = expr->GetReceiverTypes()->first(); |
8672 if (function_map->instance_type() != JS_FUNCTION_TYPE || | 8672 if (function_map->instance_type() != JS_FUNCTION_TYPE || |
8673 !expr->target()->shared()->HasBuiltinFunctionId() || | 8673 !expr->target()->shared()->HasBuiltinFunctionId() || |
8674 expr->target()->shared()->builtin_function_id() != kFunctionApply) { | 8674 expr->target()->shared()->builtin_function_id() != kFunctionApply) { |
8675 return false; | 8675 return false; |
8676 } | 8676 } |
(...skipping 22 matching lines...) Expand all Loading... |
8699 HValue* wrapped_receiver = BuildWrapReceiver(receiver, checked_function); | 8699 HValue* wrapped_receiver = BuildWrapReceiver(receiver, checked_function); |
8700 HInstruction* result = New<HApplyArguments>(function, | 8700 HInstruction* result = New<HApplyArguments>(function, |
8701 wrapped_receiver, | 8701 wrapped_receiver, |
8702 length, | 8702 length, |
8703 elements); | 8703 elements); |
8704 ast_context()->ReturnInstruction(result, expr->id()); | 8704 ast_context()->ReturnInstruction(result, expr->id()); |
8705 return true; | 8705 return true; |
8706 } else { | 8706 } else { |
8707 // We are inside inlined function and we know exactly what is inside | 8707 // We are inside inlined function and we know exactly what is inside |
8708 // arguments object. But we need to be able to materialize at deopt. | 8708 // arguments object. But we need to be able to materialize at deopt. |
8709 ASSERT_EQ(environment()->arguments_environment()->parameter_count(), | 8709 DCHECK_EQ(environment()->arguments_environment()->parameter_count(), |
8710 function_state()->entry()->arguments_object()->arguments_count()); | 8710 function_state()->entry()->arguments_object()->arguments_count()); |
8711 HArgumentsObject* args = function_state()->entry()->arguments_object(); | 8711 HArgumentsObject* args = function_state()->entry()->arguments_object(); |
8712 const ZoneList<HValue*>* arguments_values = args->arguments_values(); | 8712 const ZoneList<HValue*>* arguments_values = args->arguments_values(); |
8713 int arguments_count = arguments_values->length(); | 8713 int arguments_count = arguments_values->length(); |
8714 Push(function); | 8714 Push(function); |
8715 Push(BuildWrapReceiver(receiver, checked_function)); | 8715 Push(BuildWrapReceiver(receiver, checked_function)); |
8716 for (int i = 1; i < arguments_count; i++) { | 8716 for (int i = 1; i < arguments_count; i++) { |
8717 Push(arguments_values->at(i)); | 8717 Push(arguments_values->at(i)); |
8718 } | 8718 } |
8719 | 8719 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8767 Drop(1); | 8767 Drop(1); |
8768 } | 8768 } |
8769 ast_context()->ReturnInstruction(call, expression->id()); | 8769 ast_context()->ReturnInstruction(call, expression->id()); |
8770 } | 8770 } |
8771 | 8771 |
8772 | 8772 |
8773 HValue* HOptimizedGraphBuilder::BuildArrayIndexOf(HValue* receiver, | 8773 HValue* HOptimizedGraphBuilder::BuildArrayIndexOf(HValue* receiver, |
8774 HValue* search_element, | 8774 HValue* search_element, |
8775 ElementsKind kind, | 8775 ElementsKind kind, |
8776 ArrayIndexOfMode mode) { | 8776 ArrayIndexOfMode mode) { |
8777 ASSERT(IsFastElementsKind(kind)); | 8777 DCHECK(IsFastElementsKind(kind)); |
8778 | 8778 |
8779 NoObservableSideEffectsScope no_effects(this); | 8779 NoObservableSideEffectsScope no_effects(this); |
8780 | 8780 |
8781 HValue* elements = AddLoadElements(receiver); | 8781 HValue* elements = AddLoadElements(receiver); |
8782 HValue* length = AddLoadArrayLength(receiver, kind); | 8782 HValue* length = AddLoadArrayLength(receiver, kind); |
8783 | 8783 |
8784 HValue* initial; | 8784 HValue* initial; |
8785 HValue* terminating; | 8785 HValue* terminating; |
8786 Token::Value token; | 8786 Token::Value token; |
8787 LoopBuilder::Direction direction; | 8787 LoopBuilder::Direction direction; |
8788 if (mode == kFirstIndexOf) { | 8788 if (mode == kFirstIndexOf) { |
8789 initial = graph()->GetConstant0(); | 8789 initial = graph()->GetConstant0(); |
8790 terminating = length; | 8790 terminating = length; |
8791 token = Token::LT; | 8791 token = Token::LT; |
8792 direction = LoopBuilder::kPostIncrement; | 8792 direction = LoopBuilder::kPostIncrement; |
8793 } else { | 8793 } else { |
8794 ASSERT_EQ(kLastIndexOf, mode); | 8794 DCHECK_EQ(kLastIndexOf, mode); |
8795 initial = length; | 8795 initial = length; |
8796 terminating = graph()->GetConstant0(); | 8796 terminating = graph()->GetConstant0(); |
8797 token = Token::GT; | 8797 token = Token::GT; |
8798 direction = LoopBuilder::kPreDecrement; | 8798 direction = LoopBuilder::kPreDecrement; |
8799 } | 8799 } |
8800 | 8800 |
8801 Push(graph()->GetConstantMinus1()); | 8801 Push(graph()->GetConstantMinus1()); |
8802 if (IsFastDoubleElementsKind(kind) || IsFastSmiElementsKind(kind)) { | 8802 if (IsFastDoubleElementsKind(kind) || IsFastSmiElementsKind(kind)) { |
8803 LoopBuilder loop(this, context(), direction); | 8803 LoopBuilder loop(this, context(), direction); |
8804 { | 8804 { |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8943 | 8943 |
8944 BuildArrayCall(expr, | 8944 BuildArrayCall(expr, |
8945 expr->arguments()->length(), | 8945 expr->arguments()->length(), |
8946 function, | 8946 function, |
8947 expr->allocation_site()); | 8947 expr->allocation_site()); |
8948 return true; | 8948 return true; |
8949 } | 8949 } |
8950 | 8950 |
8951 | 8951 |
8952 void HOptimizedGraphBuilder::VisitCall(Call* expr) { | 8952 void HOptimizedGraphBuilder::VisitCall(Call* expr) { |
8953 ASSERT(!HasStackOverflow()); | 8953 DCHECK(!HasStackOverflow()); |
8954 ASSERT(current_block() != NULL); | 8954 DCHECK(current_block() != NULL); |
8955 ASSERT(current_block()->HasPredecessor()); | 8955 DCHECK(current_block()->HasPredecessor()); |
8956 Expression* callee = expr->expression(); | 8956 Expression* callee = expr->expression(); |
8957 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 8957 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
8958 HInstruction* call = NULL; | 8958 HInstruction* call = NULL; |
8959 | 8959 |
8960 Property* prop = callee->AsProperty(); | 8960 Property* prop = callee->AsProperty(); |
8961 if (prop != NULL) { | 8961 if (prop != NULL) { |
8962 CHECK_ALIVE(VisitForValue(prop->obj())); | 8962 CHECK_ALIVE(VisitForValue(prop->obj())); |
8963 HValue* receiver = Top(); | 8963 HValue* receiver = Top(); |
8964 | 8964 |
8965 SmallMapList* types; | 8965 SmallMapList* types; |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9124 | 9124 |
9125 Drop(1); // Drop the function. | 9125 Drop(1); // Drop the function. |
9126 return ast_context()->ReturnInstruction(call, expr->id()); | 9126 return ast_context()->ReturnInstruction(call, expr->id()); |
9127 } | 9127 } |
9128 | 9128 |
9129 | 9129 |
9130 void HOptimizedGraphBuilder::BuildInlinedCallArray( | 9130 void HOptimizedGraphBuilder::BuildInlinedCallArray( |
9131 Expression* expression, | 9131 Expression* expression, |
9132 int argument_count, | 9132 int argument_count, |
9133 Handle<AllocationSite> site) { | 9133 Handle<AllocationSite> site) { |
9134 ASSERT(!site.is_null()); | 9134 DCHECK(!site.is_null()); |
9135 ASSERT(argument_count >= 0 && argument_count <= 1); | 9135 DCHECK(argument_count >= 0 && argument_count <= 1); |
9136 NoObservableSideEffectsScope no_effects(this); | 9136 NoObservableSideEffectsScope no_effects(this); |
9137 | 9137 |
9138 // We should at least have the constructor on the expression stack. | 9138 // We should at least have the constructor on the expression stack. |
9139 HValue* constructor = environment()->ExpressionStackAt(argument_count); | 9139 HValue* constructor = environment()->ExpressionStackAt(argument_count); |
9140 | 9140 |
9141 // Register on the site for deoptimization if the transition feedback changes. | 9141 // Register on the site for deoptimization if the transition feedback changes. |
9142 AllocationSite::AddDependentCompilationInfo( | 9142 AllocationSite::AddDependentCompilationInfo( |
9143 site, AllocationSite::TRANSITIONS, top_info()); | 9143 site, AllocationSite::TRANSITIONS, top_info()); |
9144 ElementsKind kind = site->GetElementsKind(); | 9144 ElementsKind kind = site->GetElementsKind(); |
9145 HInstruction* site_instruction = Add<HConstant>(site); | 9145 HInstruction* site_instruction = Add<HConstant>(site); |
9146 | 9146 |
9147 // In the single constant argument case, we may have to adjust elements kind | 9147 // In the single constant argument case, we may have to adjust elements kind |
9148 // to avoid creating a packed non-empty array. | 9148 // to avoid creating a packed non-empty array. |
9149 if (argument_count == 1 && !IsHoleyElementsKind(kind)) { | 9149 if (argument_count == 1 && !IsHoleyElementsKind(kind)) { |
9150 HValue* argument = environment()->Top(); | 9150 HValue* argument = environment()->Top(); |
9151 if (argument->IsConstant()) { | 9151 if (argument->IsConstant()) { |
9152 HConstant* constant_argument = HConstant::cast(argument); | 9152 HConstant* constant_argument = HConstant::cast(argument); |
9153 ASSERT(constant_argument->HasSmiValue()); | 9153 DCHECK(constant_argument->HasSmiValue()); |
9154 int constant_array_size = constant_argument->Integer32Value(); | 9154 int constant_array_size = constant_argument->Integer32Value(); |
9155 if (constant_array_size != 0) { | 9155 if (constant_array_size != 0) { |
9156 kind = GetHoleyElementsKind(kind); | 9156 kind = GetHoleyElementsKind(kind); |
9157 } | 9157 } |
9158 } | 9158 } |
9159 } | 9159 } |
9160 | 9160 |
9161 // Build the array. | 9161 // Build the array. |
9162 JSArrayBuilder array_builder(this, | 9162 JSArrayBuilder array_builder(this, |
9163 kind, | 9163 kind, |
(...skipping 18 matching lines...) Expand all Loading... |
9182 constructor->initial_map()->InitialPropertiesLength() == 0; | 9182 constructor->initial_map()->InitialPropertiesLength() == 0; |
9183 } | 9183 } |
9184 | 9184 |
9185 | 9185 |
9186 bool HOptimizedGraphBuilder::IsCallArrayInlineable( | 9186 bool HOptimizedGraphBuilder::IsCallArrayInlineable( |
9187 int argument_count, | 9187 int argument_count, |
9188 Handle<AllocationSite> site) { | 9188 Handle<AllocationSite> site) { |
9189 Handle<JSFunction> caller = current_info()->closure(); | 9189 Handle<JSFunction> caller = current_info()->closure(); |
9190 Handle<JSFunction> target = array_function(); | 9190 Handle<JSFunction> target = array_function(); |
9191 // We should have the function plus array arguments on the environment stack. | 9191 // We should have the function plus array arguments on the environment stack. |
9192 ASSERT(environment()->length() >= (argument_count + 1)); | 9192 DCHECK(environment()->length() >= (argument_count + 1)); |
9193 ASSERT(!site.is_null()); | 9193 DCHECK(!site.is_null()); |
9194 | 9194 |
9195 bool inline_ok = false; | 9195 bool inline_ok = false; |
9196 if (site->CanInlineCall()) { | 9196 if (site->CanInlineCall()) { |
9197 // We also want to avoid inlining in certain 1 argument scenarios. | 9197 // We also want to avoid inlining in certain 1 argument scenarios. |
9198 if (argument_count == 1) { | 9198 if (argument_count == 1) { |
9199 HValue* argument = Top(); | 9199 HValue* argument = Top(); |
9200 if (argument->IsConstant()) { | 9200 if (argument->IsConstant()) { |
9201 // Do not inline if the constant length argument is not a smi or | 9201 // Do not inline if the constant length argument is not a smi or |
9202 // outside the valid range for unrolled loop initialization. | 9202 // outside the valid range for unrolled loop initialization. |
9203 HConstant* constant_argument = HConstant::cast(argument); | 9203 HConstant* constant_argument = HConstant::cast(argument); |
(...skipping 19 matching lines...) Expand all Loading... |
9223 } | 9223 } |
9224 | 9224 |
9225 if (inline_ok) { | 9225 if (inline_ok) { |
9226 TraceInline(target, caller, NULL); | 9226 TraceInline(target, caller, NULL); |
9227 } | 9227 } |
9228 return inline_ok; | 9228 return inline_ok; |
9229 } | 9229 } |
9230 | 9230 |
9231 | 9231 |
9232 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { | 9232 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { |
9233 ASSERT(!HasStackOverflow()); | 9233 DCHECK(!HasStackOverflow()); |
9234 ASSERT(current_block() != NULL); | 9234 DCHECK(current_block() != NULL); |
9235 ASSERT(current_block()->HasPredecessor()); | 9235 DCHECK(current_block()->HasPredecessor()); |
9236 if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); | 9236 if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); |
9237 int argument_count = expr->arguments()->length() + 1; // Plus constructor. | 9237 int argument_count = expr->arguments()->length() + 1; // Plus constructor. |
9238 Factory* factory = isolate()->factory(); | 9238 Factory* factory = isolate()->factory(); |
9239 | 9239 |
9240 // The constructor function is on the stack in the unoptimized code | 9240 // The constructor function is on the stack in the unoptimized code |
9241 // during evaluation of the arguments. | 9241 // during evaluation of the arguments. |
9242 CHECK_ALIVE(VisitForValue(expr->expression())); | 9242 CHECK_ALIVE(VisitForValue(expr->expression())); |
9243 HValue* function = Top(); | 9243 HValue* function = Top(); |
9244 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 9244 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
9245 | 9245 |
9246 if (FLAG_inline_construct && | 9246 if (FLAG_inline_construct && |
9247 expr->IsMonomorphic() && | 9247 expr->IsMonomorphic() && |
9248 IsAllocationInlineable(expr->target())) { | 9248 IsAllocationInlineable(expr->target())) { |
9249 Handle<JSFunction> constructor = expr->target(); | 9249 Handle<JSFunction> constructor = expr->target(); |
9250 HValue* check = Add<HCheckValue>(function, constructor); | 9250 HValue* check = Add<HCheckValue>(function, constructor); |
9251 | 9251 |
9252 // Force completion of inobject slack tracking before generating | 9252 // Force completion of inobject slack tracking before generating |
9253 // allocation code to finalize instance size. | 9253 // allocation code to finalize instance size. |
9254 if (constructor->IsInobjectSlackTrackingInProgress()) { | 9254 if (constructor->IsInobjectSlackTrackingInProgress()) { |
9255 constructor->CompleteInobjectSlackTracking(); | 9255 constructor->CompleteInobjectSlackTracking(); |
9256 } | 9256 } |
9257 | 9257 |
9258 // Calculate instance size from initial map of constructor. | 9258 // Calculate instance size from initial map of constructor. |
9259 ASSERT(constructor->has_initial_map()); | 9259 DCHECK(constructor->has_initial_map()); |
9260 Handle<Map> initial_map(constructor->initial_map()); | 9260 Handle<Map> initial_map(constructor->initial_map()); |
9261 int instance_size = initial_map->instance_size(); | 9261 int instance_size = initial_map->instance_size(); |
9262 ASSERT(initial_map->InitialPropertiesLength() == 0); | 9262 DCHECK(initial_map->InitialPropertiesLength() == 0); |
9263 | 9263 |
9264 // Allocate an instance of the implicit receiver object. | 9264 // Allocate an instance of the implicit receiver object. |
9265 HValue* size_in_bytes = Add<HConstant>(instance_size); | 9265 HValue* size_in_bytes = Add<HConstant>(instance_size); |
9266 HAllocationMode allocation_mode; | 9266 HAllocationMode allocation_mode; |
9267 if (FLAG_pretenuring_call_new) { | 9267 if (FLAG_pretenuring_call_new) { |
9268 if (FLAG_allocation_site_pretenuring) { | 9268 if (FLAG_allocation_site_pretenuring) { |
9269 // Try to use pretenuring feedback. | 9269 // Try to use pretenuring feedback. |
9270 Handle<AllocationSite> allocation_site = expr->allocation_site(); | 9270 Handle<AllocationSite> allocation_site = expr->allocation_site(); |
9271 allocation_mode = HAllocationMode(allocation_site); | 9271 allocation_mode = HAllocationMode(allocation_site); |
9272 // Take a dependency on allocation site. | 9272 // Take a dependency on allocation site. |
9273 AllocationSite::AddDependentCompilationInfo(allocation_site, | 9273 AllocationSite::AddDependentCompilationInfo(allocation_site, |
9274 AllocationSite::TENURING, | 9274 AllocationSite::TENURING, |
9275 top_info()); | 9275 top_info()); |
9276 } | 9276 } |
9277 } | 9277 } |
9278 | 9278 |
9279 HAllocate* receiver = BuildAllocate( | 9279 HAllocate* receiver = BuildAllocate( |
9280 size_in_bytes, HType::JSObject(), JS_OBJECT_TYPE, allocation_mode); | 9280 size_in_bytes, HType::JSObject(), JS_OBJECT_TYPE, allocation_mode); |
9281 receiver->set_known_initial_map(initial_map); | 9281 receiver->set_known_initial_map(initial_map); |
9282 | 9282 |
9283 // Initialize map and fields of the newly allocated object. | 9283 // Initialize map and fields of the newly allocated object. |
9284 { NoObservableSideEffectsScope no_effects(this); | 9284 { NoObservableSideEffectsScope no_effects(this); |
9285 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); | 9285 DCHECK(initial_map->instance_type() == JS_OBJECT_TYPE); |
9286 Add<HStoreNamedField>(receiver, | 9286 Add<HStoreNamedField>(receiver, |
9287 HObjectAccess::ForMapAndOffset(initial_map, JSObject::kMapOffset), | 9287 HObjectAccess::ForMapAndOffset(initial_map, JSObject::kMapOffset), |
9288 Add<HConstant>(initial_map)); | 9288 Add<HConstant>(initial_map)); |
9289 HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array()); | 9289 HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array()); |
9290 Add<HStoreNamedField>(receiver, | 9290 Add<HStoreNamedField>(receiver, |
9291 HObjectAccess::ForMapAndOffset(initial_map, | 9291 HObjectAccess::ForMapAndOffset(initial_map, |
9292 JSObject::kPropertiesOffset), | 9292 JSObject::kPropertiesOffset), |
9293 empty_fixed_array); | 9293 empty_fixed_array); |
9294 Add<HStoreNamedField>(receiver, | 9294 Add<HStoreNamedField>(receiver, |
9295 HObjectAccess::ForMapAndOffset(initial_map, | 9295 HObjectAccess::ForMapAndOffset(initial_map, |
9296 JSObject::kElementsOffset), | 9296 JSObject::kElementsOffset), |
9297 empty_fixed_array); | 9297 empty_fixed_array); |
9298 if (initial_map->inobject_properties() != 0) { | 9298 if (initial_map->inobject_properties() != 0) { |
9299 HConstant* undefined = graph()->GetConstantUndefined(); | 9299 HConstant* undefined = graph()->GetConstantUndefined(); |
9300 for (int i = 0; i < initial_map->inobject_properties(); i++) { | 9300 for (int i = 0; i < initial_map->inobject_properties(); i++) { |
9301 int property_offset = initial_map->GetInObjectPropertyOffset(i); | 9301 int property_offset = initial_map->GetInObjectPropertyOffset(i); |
9302 Add<HStoreNamedField>(receiver, | 9302 Add<HStoreNamedField>(receiver, |
9303 HObjectAccess::ForMapAndOffset(initial_map, property_offset), | 9303 HObjectAccess::ForMapAndOffset(initial_map, property_offset), |
9304 undefined); | 9304 undefined); |
9305 } | 9305 } |
9306 } | 9306 } |
9307 } | 9307 } |
9308 | 9308 |
9309 // Replace the constructor function with a newly allocated receiver using | 9309 // Replace the constructor function with a newly allocated receiver using |
9310 // the index of the receiver from the top of the expression stack. | 9310 // the index of the receiver from the top of the expression stack. |
9311 const int receiver_index = argument_count - 1; | 9311 const int receiver_index = argument_count - 1; |
9312 ASSERT(environment()->ExpressionStackAt(receiver_index) == function); | 9312 DCHECK(environment()->ExpressionStackAt(receiver_index) == function); |
9313 environment()->SetExpressionStackAt(receiver_index, receiver); | 9313 environment()->SetExpressionStackAt(receiver_index, receiver); |
9314 | 9314 |
9315 if (TryInlineConstruct(expr, receiver)) { | 9315 if (TryInlineConstruct(expr, receiver)) { |
9316 // Inlining worked, add a dependency on the initial map to make sure that | 9316 // Inlining worked, add a dependency on the initial map to make sure that |
9317 // this code is deoptimized whenever the initial map of the constructor | 9317 // this code is deoptimized whenever the initial map of the constructor |
9318 // changes. | 9318 // changes. |
9319 Map::AddDependentCompilationInfo( | 9319 Map::AddDependentCompilationInfo( |
9320 initial_map, DependentCode::kInitialMapChangedGroup, top_info()); | 9320 initial_map, DependentCode::kInitialMapChangedGroup, top_info()); |
9321 return; | 9321 return; |
9322 } | 9322 } |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9408 HObjectAccess::ForJSArrayBufferViewWeakNext(), | 9408 HObjectAccess::ForJSArrayBufferViewWeakNext(), |
9409 graph()->GetConstantUndefined()); | 9409 graph()->GetConstantUndefined()); |
9410 } | 9410 } |
9411 } | 9411 } |
9412 | 9412 |
9413 | 9413 |
9414 void HOptimizedGraphBuilder::GenerateDataViewInitialize( | 9414 void HOptimizedGraphBuilder::GenerateDataViewInitialize( |
9415 CallRuntime* expr) { | 9415 CallRuntime* expr) { |
9416 ZoneList<Expression*>* arguments = expr->arguments(); | 9416 ZoneList<Expression*>* arguments = expr->arguments(); |
9417 | 9417 |
9418 ASSERT(arguments->length()== 4); | 9418 DCHECK(arguments->length()== 4); |
9419 CHECK_ALIVE(VisitForValue(arguments->at(0))); | 9419 CHECK_ALIVE(VisitForValue(arguments->at(0))); |
9420 HValue* obj = Pop(); | 9420 HValue* obj = Pop(); |
9421 | 9421 |
9422 CHECK_ALIVE(VisitForValue(arguments->at(1))); | 9422 CHECK_ALIVE(VisitForValue(arguments->at(1))); |
9423 HValue* buffer = Pop(); | 9423 HValue* buffer = Pop(); |
9424 | 9424 |
9425 CHECK_ALIVE(VisitForValue(arguments->at(2))); | 9425 CHECK_ALIVE(VisitForValue(arguments->at(2))); |
9426 HValue* byte_offset = Pop(); | 9426 HValue* byte_offset = Pop(); |
9427 | 9427 |
9428 CHECK_ALIVE(VisitForValue(arguments->at(3))); | 9428 CHECK_ALIVE(VisitForValue(arguments->at(3))); |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9552 void HOptimizedGraphBuilder::GenerateTypedArrayInitialize( | 9552 void HOptimizedGraphBuilder::GenerateTypedArrayInitialize( |
9553 CallRuntime* expr) { | 9553 CallRuntime* expr) { |
9554 ZoneList<Expression*>* arguments = expr->arguments(); | 9554 ZoneList<Expression*>* arguments = expr->arguments(); |
9555 | 9555 |
9556 static const int kObjectArg = 0; | 9556 static const int kObjectArg = 0; |
9557 static const int kArrayIdArg = 1; | 9557 static const int kArrayIdArg = 1; |
9558 static const int kBufferArg = 2; | 9558 static const int kBufferArg = 2; |
9559 static const int kByteOffsetArg = 3; | 9559 static const int kByteOffsetArg = 3; |
9560 static const int kByteLengthArg = 4; | 9560 static const int kByteLengthArg = 4; |
9561 static const int kArgsLength = 5; | 9561 static const int kArgsLength = 5; |
9562 ASSERT(arguments->length() == kArgsLength); | 9562 DCHECK(arguments->length() == kArgsLength); |
9563 | 9563 |
9564 | 9564 |
9565 CHECK_ALIVE(VisitForValue(arguments->at(kObjectArg))); | 9565 CHECK_ALIVE(VisitForValue(arguments->at(kObjectArg))); |
9566 HValue* obj = Pop(); | 9566 HValue* obj = Pop(); |
9567 | 9567 |
9568 if (arguments->at(kArrayIdArg)->IsLiteral()) { | 9568 if (arguments->at(kArrayIdArg)->IsLiteral()) { |
9569 // This should never happen in real use, but can happen when fuzzing. | 9569 // This should never happen in real use, but can happen when fuzzing. |
9570 // Just bail out. | 9570 // Just bail out. |
9571 Bailout(kNeedSmiLiteral); | 9571 Bailout(kNeedSmiLiteral); |
9572 return; | 9572 return; |
(...skipping 21 matching lines...) Expand all Loading... |
9594 | 9594 |
9595 if (arguments->at(kByteOffsetArg)->IsLiteral() | 9595 if (arguments->at(kByteOffsetArg)->IsLiteral() |
9596 && Smi::FromInt(0) == | 9596 && Smi::FromInt(0) == |
9597 *static_cast<Literal*>(arguments->at(kByteOffsetArg))->value()) { | 9597 *static_cast<Literal*>(arguments->at(kByteOffsetArg))->value()) { |
9598 byte_offset = Add<HConstant>(static_cast<int32_t>(0)); | 9598 byte_offset = Add<HConstant>(static_cast<int32_t>(0)); |
9599 is_zero_byte_offset = true; | 9599 is_zero_byte_offset = true; |
9600 } else { | 9600 } else { |
9601 CHECK_ALIVE(VisitForValue(arguments->at(kByteOffsetArg))); | 9601 CHECK_ALIVE(VisitForValue(arguments->at(kByteOffsetArg))); |
9602 byte_offset = Pop(); | 9602 byte_offset = Pop(); |
9603 is_zero_byte_offset = false; | 9603 is_zero_byte_offset = false; |
9604 ASSERT(buffer != NULL); | 9604 DCHECK(buffer != NULL); |
9605 } | 9605 } |
9606 | 9606 |
9607 CHECK_ALIVE(VisitForValue(arguments->at(kByteLengthArg))); | 9607 CHECK_ALIVE(VisitForValue(arguments->at(kByteLengthArg))); |
9608 HValue* byte_length = Pop(); | 9608 HValue* byte_length = Pop(); |
9609 | 9609 |
9610 NoObservableSideEffectsScope scope(this); | 9610 NoObservableSideEffectsScope scope(this); |
9611 IfBuilder byte_offset_smi(this); | 9611 IfBuilder byte_offset_smi(this); |
9612 | 9612 |
9613 if (!is_zero_byte_offset) { | 9613 if (!is_zero_byte_offset) { |
9614 byte_offset_smi.If<HIsSmiAndBranch>(byte_offset); | 9614 byte_offset_smi.If<HIsSmiAndBranch>(byte_offset); |
(...skipping 27 matching lines...) Expand all Loading... |
9642 length); | 9642 length); |
9643 | 9643 |
9644 HValue* elements; | 9644 HValue* elements; |
9645 if (buffer != NULL) { | 9645 if (buffer != NULL) { |
9646 elements = BuildAllocateExternalElements( | 9646 elements = BuildAllocateExternalElements( |
9647 array_type, is_zero_byte_offset, buffer, byte_offset, length); | 9647 array_type, is_zero_byte_offset, buffer, byte_offset, length); |
9648 Handle<Map> obj_map = TypedArrayMap( | 9648 Handle<Map> obj_map = TypedArrayMap( |
9649 isolate(), array_type, external_elements_kind); | 9649 isolate(), array_type, external_elements_kind); |
9650 AddStoreMapConstant(obj, obj_map); | 9650 AddStoreMapConstant(obj, obj_map); |
9651 } else { | 9651 } else { |
9652 ASSERT(is_zero_byte_offset); | 9652 DCHECK(is_zero_byte_offset); |
9653 elements = BuildAllocateFixedTypedArray( | 9653 elements = BuildAllocateFixedTypedArray( |
9654 array_type, element_size, fixed_elements_kind, | 9654 array_type, element_size, fixed_elements_kind, |
9655 byte_length, length); | 9655 byte_length, length); |
9656 } | 9656 } |
9657 Add<HStoreNamedField>( | 9657 Add<HStoreNamedField>( |
9658 obj, HObjectAccess::ForElementsPointer(), elements); | 9658 obj, HObjectAccess::ForElementsPointer(), elements); |
9659 } | 9659 } |
9660 | 9660 |
9661 if (!is_zero_byte_offset) { | 9661 if (!is_zero_byte_offset) { |
9662 byte_offset_smi.Else(); | 9662 byte_offset_smi.Else(); |
9663 { // byte_offset is not Smi. | 9663 { // byte_offset is not Smi. |
9664 Push(obj); | 9664 Push(obj); |
9665 CHECK_ALIVE(VisitForValue(arguments->at(kArrayIdArg))); | 9665 CHECK_ALIVE(VisitForValue(arguments->at(kArrayIdArg))); |
9666 Push(buffer); | 9666 Push(buffer); |
9667 Push(byte_offset); | 9667 Push(byte_offset); |
9668 Push(byte_length); | 9668 Push(byte_length); |
9669 PushArgumentsFromEnvironment(kArgsLength); | 9669 PushArgumentsFromEnvironment(kArgsLength); |
9670 Add<HCallRuntime>(expr->name(), expr->function(), kArgsLength); | 9670 Add<HCallRuntime>(expr->name(), expr->function(), kArgsLength); |
9671 } | 9671 } |
9672 } | 9672 } |
9673 byte_offset_smi.End(); | 9673 byte_offset_smi.End(); |
9674 } | 9674 } |
9675 | 9675 |
9676 | 9676 |
9677 void HOptimizedGraphBuilder::GenerateMaxSmi(CallRuntime* expr) { | 9677 void HOptimizedGraphBuilder::GenerateMaxSmi(CallRuntime* expr) { |
9678 ASSERT(expr->arguments()->length() == 0); | 9678 DCHECK(expr->arguments()->length() == 0); |
9679 HConstant* max_smi = New<HConstant>(static_cast<int32_t>(Smi::kMaxValue)); | 9679 HConstant* max_smi = New<HConstant>(static_cast<int32_t>(Smi::kMaxValue)); |
9680 return ast_context()->ReturnInstruction(max_smi, expr->id()); | 9680 return ast_context()->ReturnInstruction(max_smi, expr->id()); |
9681 } | 9681 } |
9682 | 9682 |
9683 | 9683 |
9684 void HOptimizedGraphBuilder::GenerateTypedArrayMaxSizeInHeap( | 9684 void HOptimizedGraphBuilder::GenerateTypedArrayMaxSizeInHeap( |
9685 CallRuntime* expr) { | 9685 CallRuntime* expr) { |
9686 ASSERT(expr->arguments()->length() == 0); | 9686 DCHECK(expr->arguments()->length() == 0); |
9687 HConstant* result = New<HConstant>(static_cast<int32_t>( | 9687 HConstant* result = New<HConstant>(static_cast<int32_t>( |
9688 FLAG_typed_array_max_size_in_heap)); | 9688 FLAG_typed_array_max_size_in_heap)); |
9689 return ast_context()->ReturnInstruction(result, expr->id()); | 9689 return ast_context()->ReturnInstruction(result, expr->id()); |
9690 } | 9690 } |
9691 | 9691 |
9692 | 9692 |
9693 void HOptimizedGraphBuilder::GenerateArrayBufferGetByteLength( | 9693 void HOptimizedGraphBuilder::GenerateArrayBufferGetByteLength( |
9694 CallRuntime* expr) { | 9694 CallRuntime* expr) { |
9695 ASSERT(expr->arguments()->length() == 1); | 9695 DCHECK(expr->arguments()->length() == 1); |
9696 CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); | 9696 CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); |
9697 HValue* buffer = Pop(); | 9697 HValue* buffer = Pop(); |
9698 HInstruction* result = New<HLoadNamedField>( | 9698 HInstruction* result = New<HLoadNamedField>( |
9699 buffer, | 9699 buffer, |
9700 static_cast<HValue*>(NULL), | 9700 static_cast<HValue*>(NULL), |
9701 HObjectAccess::ForJSArrayBufferByteLength()); | 9701 HObjectAccess::ForJSArrayBufferByteLength()); |
9702 return ast_context()->ReturnInstruction(result, expr->id()); | 9702 return ast_context()->ReturnInstruction(result, expr->id()); |
9703 } | 9703 } |
9704 | 9704 |
9705 | 9705 |
9706 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteLength( | 9706 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteLength( |
9707 CallRuntime* expr) { | 9707 CallRuntime* expr) { |
9708 ASSERT(expr->arguments()->length() == 1); | 9708 DCHECK(expr->arguments()->length() == 1); |
9709 CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); | 9709 CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); |
9710 HValue* buffer = Pop(); | 9710 HValue* buffer = Pop(); |
9711 HInstruction* result = New<HLoadNamedField>( | 9711 HInstruction* result = New<HLoadNamedField>( |
9712 buffer, | 9712 buffer, |
9713 static_cast<HValue*>(NULL), | 9713 static_cast<HValue*>(NULL), |
9714 HObjectAccess::ForJSArrayBufferViewByteLength()); | 9714 HObjectAccess::ForJSArrayBufferViewByteLength()); |
9715 return ast_context()->ReturnInstruction(result, expr->id()); | 9715 return ast_context()->ReturnInstruction(result, expr->id()); |
9716 } | 9716 } |
9717 | 9717 |
9718 | 9718 |
9719 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteOffset( | 9719 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteOffset( |
9720 CallRuntime* expr) { | 9720 CallRuntime* expr) { |
9721 ASSERT(expr->arguments()->length() == 1); | 9721 DCHECK(expr->arguments()->length() == 1); |
9722 CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); | 9722 CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); |
9723 HValue* buffer = Pop(); | 9723 HValue* buffer = Pop(); |
9724 HInstruction* result = New<HLoadNamedField>( | 9724 HInstruction* result = New<HLoadNamedField>( |
9725 buffer, | 9725 buffer, |
9726 static_cast<HValue*>(NULL), | 9726 static_cast<HValue*>(NULL), |
9727 HObjectAccess::ForJSArrayBufferViewByteOffset()); | 9727 HObjectAccess::ForJSArrayBufferViewByteOffset()); |
9728 return ast_context()->ReturnInstruction(result, expr->id()); | 9728 return ast_context()->ReturnInstruction(result, expr->id()); |
9729 } | 9729 } |
9730 | 9730 |
9731 | 9731 |
9732 void HOptimizedGraphBuilder::GenerateTypedArrayGetLength( | 9732 void HOptimizedGraphBuilder::GenerateTypedArrayGetLength( |
9733 CallRuntime* expr) { | 9733 CallRuntime* expr) { |
9734 ASSERT(expr->arguments()->length() == 1); | 9734 DCHECK(expr->arguments()->length() == 1); |
9735 CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); | 9735 CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); |
9736 HValue* buffer = Pop(); | 9736 HValue* buffer = Pop(); |
9737 HInstruction* result = New<HLoadNamedField>( | 9737 HInstruction* result = New<HLoadNamedField>( |
9738 buffer, | 9738 buffer, |
9739 static_cast<HValue*>(NULL), | 9739 static_cast<HValue*>(NULL), |
9740 HObjectAccess::ForJSTypedArrayLength()); | 9740 HObjectAccess::ForJSTypedArrayLength()); |
9741 return ast_context()->ReturnInstruction(result, expr->id()); | 9741 return ast_context()->ReturnInstruction(result, expr->id()); |
9742 } | 9742 } |
9743 | 9743 |
9744 | 9744 |
9745 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { | 9745 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
9746 ASSERT(!HasStackOverflow()); | 9746 DCHECK(!HasStackOverflow()); |
9747 ASSERT(current_block() != NULL); | 9747 DCHECK(current_block() != NULL); |
9748 ASSERT(current_block()->HasPredecessor()); | 9748 DCHECK(current_block()->HasPredecessor()); |
9749 if (expr->is_jsruntime()) { | 9749 if (expr->is_jsruntime()) { |
9750 return Bailout(kCallToAJavaScriptRuntimeFunction); | 9750 return Bailout(kCallToAJavaScriptRuntimeFunction); |
9751 } | 9751 } |
9752 | 9752 |
9753 const Runtime::Function* function = expr->function(); | 9753 const Runtime::Function* function = expr->function(); |
9754 ASSERT(function != NULL); | 9754 DCHECK(function != NULL); |
9755 | 9755 |
9756 if (function->intrinsic_type == Runtime::INLINE || | 9756 if (function->intrinsic_type == Runtime::INLINE || |
9757 function->intrinsic_type == Runtime::INLINE_OPTIMIZED) { | 9757 function->intrinsic_type == Runtime::INLINE_OPTIMIZED) { |
9758 ASSERT(expr->name()->length() > 0); | 9758 DCHECK(expr->name()->length() > 0); |
9759 ASSERT(expr->name()->Get(0) == '_'); | 9759 DCHECK(expr->name()->Get(0) == '_'); |
9760 // Call to an inline function. | 9760 // Call to an inline function. |
9761 int lookup_index = static_cast<int>(function->function_id) - | 9761 int lookup_index = static_cast<int>(function->function_id) - |
9762 static_cast<int>(Runtime::kFirstInlineFunction); | 9762 static_cast<int>(Runtime::kFirstInlineFunction); |
9763 ASSERT(lookup_index >= 0); | 9763 DCHECK(lookup_index >= 0); |
9764 ASSERT(static_cast<size_t>(lookup_index) < | 9764 DCHECK(static_cast<size_t>(lookup_index) < |
9765 ARRAY_SIZE(kInlineFunctionGenerators)); | 9765 ARRAY_SIZE(kInlineFunctionGenerators)); |
9766 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; | 9766 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; |
9767 | 9767 |
9768 // Call the inline code generator using the pointer-to-member. | 9768 // Call the inline code generator using the pointer-to-member. |
9769 (this->*generator)(expr); | 9769 (this->*generator)(expr); |
9770 } else { | 9770 } else { |
9771 ASSERT(function->intrinsic_type == Runtime::RUNTIME); | 9771 DCHECK(function->intrinsic_type == Runtime::RUNTIME); |
9772 Handle<String> name = expr->name(); | 9772 Handle<String> name = expr->name(); |
9773 int argument_count = expr->arguments()->length(); | 9773 int argument_count = expr->arguments()->length(); |
9774 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 9774 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
9775 PushArgumentsFromEnvironment(argument_count); | 9775 PushArgumentsFromEnvironment(argument_count); |
9776 HCallRuntime* call = New<HCallRuntime>(name, function, | 9776 HCallRuntime* call = New<HCallRuntime>(name, function, |
9777 argument_count); | 9777 argument_count); |
9778 return ast_context()->ReturnInstruction(call, expr->id()); | 9778 return ast_context()->ReturnInstruction(call, expr->id()); |
9779 } | 9779 } |
9780 } | 9780 } |
9781 | 9781 |
9782 | 9782 |
9783 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { | 9783 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
9784 ASSERT(!HasStackOverflow()); | 9784 DCHECK(!HasStackOverflow()); |
9785 ASSERT(current_block() != NULL); | 9785 DCHECK(current_block() != NULL); |
9786 ASSERT(current_block()->HasPredecessor()); | 9786 DCHECK(current_block()->HasPredecessor()); |
9787 switch (expr->op()) { | 9787 switch (expr->op()) { |
9788 case Token::DELETE: return VisitDelete(expr); | 9788 case Token::DELETE: return VisitDelete(expr); |
9789 case Token::VOID: return VisitVoid(expr); | 9789 case Token::VOID: return VisitVoid(expr); |
9790 case Token::TYPEOF: return VisitTypeof(expr); | 9790 case Token::TYPEOF: return VisitTypeof(expr); |
9791 case Token::NOT: return VisitNot(expr); | 9791 case Token::NOT: return VisitNot(expr); |
9792 default: UNREACHABLE(); | 9792 default: UNREACHABLE(); |
9793 } | 9793 } |
9794 } | 9794 } |
9795 | 9795 |
9796 | 9796 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9853 context->if_false(), | 9853 context->if_false(), |
9854 context->if_true()); | 9854 context->if_true()); |
9855 return; | 9855 return; |
9856 } | 9856 } |
9857 | 9857 |
9858 if (ast_context()->IsEffect()) { | 9858 if (ast_context()->IsEffect()) { |
9859 VisitForEffect(expr->expression()); | 9859 VisitForEffect(expr->expression()); |
9860 return; | 9860 return; |
9861 } | 9861 } |
9862 | 9862 |
9863 ASSERT(ast_context()->IsValue()); | 9863 DCHECK(ast_context()->IsValue()); |
9864 HBasicBlock* materialize_false = graph()->CreateBasicBlock(); | 9864 HBasicBlock* materialize_false = graph()->CreateBasicBlock(); |
9865 HBasicBlock* materialize_true = graph()->CreateBasicBlock(); | 9865 HBasicBlock* materialize_true = graph()->CreateBasicBlock(); |
9866 CHECK_BAILOUT(VisitForControl(expr->expression(), | 9866 CHECK_BAILOUT(VisitForControl(expr->expression(), |
9867 materialize_false, | 9867 materialize_false, |
9868 materialize_true)); | 9868 materialize_true)); |
9869 | 9869 |
9870 if (materialize_false->HasPredecessor()) { | 9870 if (materialize_false->HasPredecessor()) { |
9871 materialize_false->SetJoinId(expr->MaterializeFalseId()); | 9871 materialize_false->SetJoinId(expr->MaterializeFalseId()); |
9872 set_current_block(materialize_false); | 9872 set_current_block(materialize_false); |
9873 Push(graph()->GetConstantFalse()); | 9873 Push(graph()->GetConstantFalse()); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9939 HValue* value) { | 9939 HValue* value) { |
9940 EffectContext for_effect(this); | 9940 EffectContext for_effect(this); |
9941 Push(object); | 9941 Push(object); |
9942 if (key != NULL) Push(key); | 9942 if (key != NULL) Push(key); |
9943 Push(value); | 9943 Push(value); |
9944 BuildStore(expr, prop, ast_id, return_id); | 9944 BuildStore(expr, prop, ast_id, return_id); |
9945 } | 9945 } |
9946 | 9946 |
9947 | 9947 |
9948 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { | 9948 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { |
9949 ASSERT(!HasStackOverflow()); | 9949 DCHECK(!HasStackOverflow()); |
9950 ASSERT(current_block() != NULL); | 9950 DCHECK(current_block() != NULL); |
9951 ASSERT(current_block()->HasPredecessor()); | 9951 DCHECK(current_block()->HasPredecessor()); |
9952 if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); | 9952 if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); |
9953 Expression* target = expr->expression(); | 9953 Expression* target = expr->expression(); |
9954 VariableProxy* proxy = target->AsVariableProxy(); | 9954 VariableProxy* proxy = target->AsVariableProxy(); |
9955 Property* prop = target->AsProperty(); | 9955 Property* prop = target->AsProperty(); |
9956 if (proxy == NULL && prop == NULL) { | 9956 if (proxy == NULL && prop == NULL) { |
9957 return Bailout(kInvalidLhsInCountOperation); | 9957 return Bailout(kInvalidLhsInCountOperation); |
9958 } | 9958 } |
9959 | 9959 |
9960 // Match the full code generator stack by simulating an extra stack | 9960 // Match the full code generator stack by simulating an extra stack |
9961 // element for postfix operations in a non-effect context. The return | 9961 // element for postfix operations in a non-effect context. The return |
9962 // value is ToNumber(input). | 9962 // value is ToNumber(input). |
9963 bool returns_original_input = | 9963 bool returns_original_input = |
9964 expr->is_postfix() && !ast_context()->IsEffect(); | 9964 expr->is_postfix() && !ast_context()->IsEffect(); |
9965 HValue* input = NULL; // ToNumber(original_input). | 9965 HValue* input = NULL; // ToNumber(original_input). |
9966 HValue* after = NULL; // The result after incrementing or decrementing. | 9966 HValue* after = NULL; // The result after incrementing or decrementing. |
9967 | 9967 |
9968 if (proxy != NULL) { | 9968 if (proxy != NULL) { |
9969 Variable* var = proxy->var(); | 9969 Variable* var = proxy->var(); |
9970 if (var->mode() == CONST_LEGACY) { | 9970 if (var->mode() == CONST_LEGACY) { |
9971 return Bailout(kUnsupportedCountOperationWithConst); | 9971 return Bailout(kUnsupportedCountOperationWithConst); |
9972 } | 9972 } |
9973 // Argument of the count operation is a variable, not a property. | 9973 // Argument of the count operation is a variable, not a property. |
9974 ASSERT(prop == NULL); | 9974 DCHECK(prop == NULL); |
9975 CHECK_ALIVE(VisitForValue(target)); | 9975 CHECK_ALIVE(VisitForValue(target)); |
9976 | 9976 |
9977 after = BuildIncrement(returns_original_input, expr); | 9977 after = BuildIncrement(returns_original_input, expr); |
9978 input = returns_original_input ? Top() : Pop(); | 9978 input = returns_original_input ? Top() : Pop(); |
9979 Push(after); | 9979 Push(after); |
9980 | 9980 |
9981 switch (var->location()) { | 9981 switch (var->location()) { |
9982 case Variable::UNALLOCATED: | 9982 case Variable::UNALLOCATED: |
9983 HandleGlobalVariableAssignment(var, | 9983 HandleGlobalVariableAssignment(var, |
9984 after, | 9984 after, |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10019 | 10019 |
10020 case Variable::LOOKUP: | 10020 case Variable::LOOKUP: |
10021 return Bailout(kLookupVariableInCountOperation); | 10021 return Bailout(kLookupVariableInCountOperation); |
10022 } | 10022 } |
10023 | 10023 |
10024 Drop(returns_original_input ? 2 : 1); | 10024 Drop(returns_original_input ? 2 : 1); |
10025 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); | 10025 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); |
10026 } | 10026 } |
10027 | 10027 |
10028 // Argument of the count operation is a property. | 10028 // Argument of the count operation is a property. |
10029 ASSERT(prop != NULL); | 10029 DCHECK(prop != NULL); |
10030 if (returns_original_input) Push(graph()->GetConstantUndefined()); | 10030 if (returns_original_input) Push(graph()->GetConstantUndefined()); |
10031 | 10031 |
10032 CHECK_ALIVE(VisitForValue(prop->obj())); | 10032 CHECK_ALIVE(VisitForValue(prop->obj())); |
10033 HValue* object = Top(); | 10033 HValue* object = Top(); |
10034 | 10034 |
10035 HValue* key = NULL; | 10035 HValue* key = NULL; |
10036 if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) { | 10036 if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) { |
10037 CHECK_ALIVE(VisitForValue(prop->key())); | 10037 CHECK_ALIVE(VisitForValue(prop->key())); |
10038 key = Top(); | 10038 key = Top(); |
10039 } | 10039 } |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10169 | 10169 |
10170 // Separate the number type from the rest. | 10170 // Separate the number type from the rest. |
10171 Type* expected_obj = | 10171 Type* expected_obj = |
10172 Type::Intersect(expected_type, Type::NonNumber(zone()), zone()); | 10172 Type::Intersect(expected_type, Type::NonNumber(zone()), zone()); |
10173 Type* expected_number = | 10173 Type* expected_number = |
10174 Type::Intersect(expected_type, Type::Number(zone()), zone()); | 10174 Type::Intersect(expected_type, Type::Number(zone()), zone()); |
10175 | 10175 |
10176 // We expect to get a number. | 10176 // We expect to get a number. |
10177 // (We need to check first, since Type::None->Is(Type::Any()) == true. | 10177 // (We need to check first, since Type::None->Is(Type::Any()) == true. |
10178 if (expected_obj->Is(Type::None())) { | 10178 if (expected_obj->Is(Type::None())) { |
10179 ASSERT(!expected_number->Is(Type::None(zone()))); | 10179 DCHECK(!expected_number->Is(Type::None(zone()))); |
10180 return value; | 10180 return value; |
10181 } | 10181 } |
10182 | 10182 |
10183 if (expected_obj->Is(Type::Undefined(zone()))) { | 10183 if (expected_obj->Is(Type::Undefined(zone()))) { |
10184 // This is already done by HChange. | 10184 // This is already done by HChange. |
10185 *expected = Type::Union(expected_number, Type::Number(zone()), zone()); | 10185 *expected = Type::Union(expected_number, Type::Number(zone()), zone()); |
10186 return value; | 10186 return value; |
10187 } | 10187 } |
10188 | 10188 |
10189 return value; | 10189 return value; |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10272 left = BuildCheckString(left); | 10272 left = BuildCheckString(left); |
10273 } | 10273 } |
10274 | 10274 |
10275 // Validate type feedback for right argument. | 10275 // Validate type feedback for right argument. |
10276 if (right_type->Is(Type::String())) { | 10276 if (right_type->Is(Type::String())) { |
10277 right = BuildCheckString(right); | 10277 right = BuildCheckString(right); |
10278 } | 10278 } |
10279 | 10279 |
10280 // Convert left argument as necessary. | 10280 // Convert left argument as necessary. |
10281 if (left_type->Is(Type::Number())) { | 10281 if (left_type->Is(Type::Number())) { |
10282 ASSERT(right_type->Is(Type::String())); | 10282 DCHECK(right_type->Is(Type::String())); |
10283 left = BuildNumberToString(left, left_type); | 10283 left = BuildNumberToString(left, left_type); |
10284 } else if (!left_type->Is(Type::String())) { | 10284 } else if (!left_type->Is(Type::String())) { |
10285 ASSERT(right_type->Is(Type::String())); | 10285 DCHECK(right_type->Is(Type::String())); |
10286 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_RIGHT); | 10286 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_RIGHT); |
10287 Add<HPushArguments>(left, right); | 10287 Add<HPushArguments>(left, right); |
10288 return AddUncasted<HInvokeFunction>(function, 2); | 10288 return AddUncasted<HInvokeFunction>(function, 2); |
10289 } | 10289 } |
10290 | 10290 |
10291 // Convert right argument as necessary. | 10291 // Convert right argument as necessary. |
10292 if (right_type->Is(Type::Number())) { | 10292 if (right_type->Is(Type::Number())) { |
10293 ASSERT(left_type->Is(Type::String())); | 10293 DCHECK(left_type->Is(Type::String())); |
10294 right = BuildNumberToString(right, right_type); | 10294 right = BuildNumberToString(right, right_type); |
10295 } else if (!right_type->Is(Type::String())) { | 10295 } else if (!right_type->Is(Type::String())) { |
10296 ASSERT(left_type->Is(Type::String())); | 10296 DCHECK(left_type->Is(Type::String())); |
10297 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT); | 10297 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT); |
10298 Add<HPushArguments>(left, right); | 10298 Add<HPushArguments>(left, right); |
10299 return AddUncasted<HInvokeFunction>(function, 2); | 10299 return AddUncasted<HInvokeFunction>(function, 2); |
10300 } | 10300 } |
10301 | 10301 |
10302 // Fast path for empty constant strings. | 10302 // Fast path for empty constant strings. |
10303 if (left->IsConstant() && | 10303 if (left->IsConstant() && |
10304 HConstant::cast(left)->HasStringValue() && | 10304 HConstant::cast(left)->HasStringValue() && |
10305 HConstant::cast(left)->StringValue()->length() == 0) { | 10305 HConstant::cast(left)->StringValue()->length() == 0) { |
10306 return right; | 10306 return right; |
10307 } | 10307 } |
10308 if (right->IsConstant() && | 10308 if (right->IsConstant() && |
10309 HConstant::cast(right)->HasStringValue() && | 10309 HConstant::cast(right)->HasStringValue() && |
10310 HConstant::cast(right)->StringValue()->length() == 0) { | 10310 HConstant::cast(right)->StringValue()->length() == 0) { |
10311 return left; | 10311 return left; |
10312 } | 10312 } |
10313 | 10313 |
10314 // Register the dependent code with the allocation site. | 10314 // Register the dependent code with the allocation site. |
10315 if (!allocation_mode.feedback_site().is_null()) { | 10315 if (!allocation_mode.feedback_site().is_null()) { |
10316 ASSERT(!graph()->info()->IsStub()); | 10316 DCHECK(!graph()->info()->IsStub()); |
10317 Handle<AllocationSite> site(allocation_mode.feedback_site()); | 10317 Handle<AllocationSite> site(allocation_mode.feedback_site()); |
10318 AllocationSite::AddDependentCompilationInfo( | 10318 AllocationSite::AddDependentCompilationInfo( |
10319 site, AllocationSite::TENURING, top_info()); | 10319 site, AllocationSite::TENURING, top_info()); |
10320 } | 10320 } |
10321 | 10321 |
10322 // Inline the string addition into the stub when creating allocation | 10322 // Inline the string addition into the stub when creating allocation |
10323 // mementos to gather allocation site feedback, or if we can statically | 10323 // mementos to gather allocation site feedback, or if we can statically |
10324 // infer that we're going to create a cons string. | 10324 // infer that we're going to create a cons string. |
10325 if ((graph()->info()->IsStub() && | 10325 if ((graph()->info()->IsStub() && |
10326 allocation_mode.CreateAllocationMementos()) || | 10326 allocation_mode.CreateAllocationMementos()) || |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10447 static bool IsClassOfTest(CompareOperation* expr) { | 10447 static bool IsClassOfTest(CompareOperation* expr) { |
10448 if (expr->op() != Token::EQ_STRICT) return false; | 10448 if (expr->op() != Token::EQ_STRICT) return false; |
10449 CallRuntime* call = expr->left()->AsCallRuntime(); | 10449 CallRuntime* call = expr->left()->AsCallRuntime(); |
10450 if (call == NULL) return false; | 10450 if (call == NULL) return false; |
10451 Literal* literal = expr->right()->AsLiteral(); | 10451 Literal* literal = expr->right()->AsLiteral(); |
10452 if (literal == NULL) return false; | 10452 if (literal == NULL) return false; |
10453 if (!literal->value()->IsString()) return false; | 10453 if (!literal->value()->IsString()) return false; |
10454 if (!call->name()->IsOneByteEqualTo(STATIC_ASCII_VECTOR("_ClassOf"))) { | 10454 if (!call->name()->IsOneByteEqualTo(STATIC_ASCII_VECTOR("_ClassOf"))) { |
10455 return false; | 10455 return false; |
10456 } | 10456 } |
10457 ASSERT(call->arguments()->length() == 1); | 10457 DCHECK(call->arguments()->length() == 1); |
10458 return true; | 10458 return true; |
10459 } | 10459 } |
10460 | 10460 |
10461 | 10461 |
10462 void HOptimizedGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { | 10462 void HOptimizedGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { |
10463 ASSERT(!HasStackOverflow()); | 10463 DCHECK(!HasStackOverflow()); |
10464 ASSERT(current_block() != NULL); | 10464 DCHECK(current_block() != NULL); |
10465 ASSERT(current_block()->HasPredecessor()); | 10465 DCHECK(current_block()->HasPredecessor()); |
10466 switch (expr->op()) { | 10466 switch (expr->op()) { |
10467 case Token::COMMA: | 10467 case Token::COMMA: |
10468 return VisitComma(expr); | 10468 return VisitComma(expr); |
10469 case Token::OR: | 10469 case Token::OR: |
10470 case Token::AND: | 10470 case Token::AND: |
10471 return VisitLogicalExpression(expr); | 10471 return VisitLogicalExpression(expr); |
10472 default: | 10472 default: |
10473 return VisitArithmeticExpression(expr); | 10473 return VisitArithmeticExpression(expr); |
10474 } | 10474 } |
10475 } | 10475 } |
(...skipping 26 matching lines...) Expand all Loading... |
10502 // Translate right subexpression by visiting it in the same AST | 10502 // Translate right subexpression by visiting it in the same AST |
10503 // context as the entire expression. | 10503 // context as the entire expression. |
10504 if (eval_right->HasPredecessor()) { | 10504 if (eval_right->HasPredecessor()) { |
10505 eval_right->SetJoinId(expr->RightId()); | 10505 eval_right->SetJoinId(expr->RightId()); |
10506 set_current_block(eval_right); | 10506 set_current_block(eval_right); |
10507 Visit(expr->right()); | 10507 Visit(expr->right()); |
10508 } | 10508 } |
10509 | 10509 |
10510 } else if (ast_context()->IsValue()) { | 10510 } else if (ast_context()->IsValue()) { |
10511 CHECK_ALIVE(VisitForValue(expr->left())); | 10511 CHECK_ALIVE(VisitForValue(expr->left())); |
10512 ASSERT(current_block() != NULL); | 10512 DCHECK(current_block() != NULL); |
10513 HValue* left_value = Top(); | 10513 HValue* left_value = Top(); |
10514 | 10514 |
10515 // Short-circuit left values that always evaluate to the same boolean value. | 10515 // Short-circuit left values that always evaluate to the same boolean value. |
10516 if (expr->left()->ToBooleanIsTrue() || expr->left()->ToBooleanIsFalse()) { | 10516 if (expr->left()->ToBooleanIsTrue() || expr->left()->ToBooleanIsFalse()) { |
10517 // l (evals true) && r -> r | 10517 // l (evals true) && r -> r |
10518 // l (evals true) || r -> l | 10518 // l (evals true) || r -> l |
10519 // l (evals false) && r -> l | 10519 // l (evals false) && r -> l |
10520 // l (evals false) || r -> r | 10520 // l (evals false) || r -> r |
10521 if (is_logical_and == expr->left()->ToBooleanIsTrue()) { | 10521 if (is_logical_and == expr->left()->ToBooleanIsTrue()) { |
10522 Drop(1); | 10522 Drop(1); |
(...skipping 14 matching lines...) Expand all Loading... |
10537 set_current_block(eval_right); | 10537 set_current_block(eval_right); |
10538 Drop(1); // Value of the left subexpression. | 10538 Drop(1); // Value of the left subexpression. |
10539 CHECK_BAILOUT(VisitForValue(expr->right())); | 10539 CHECK_BAILOUT(VisitForValue(expr->right())); |
10540 | 10540 |
10541 HBasicBlock* join_block = | 10541 HBasicBlock* join_block = |
10542 CreateJoin(empty_block, current_block(), expr->id()); | 10542 CreateJoin(empty_block, current_block(), expr->id()); |
10543 set_current_block(join_block); | 10543 set_current_block(join_block); |
10544 return ast_context()->ReturnValue(Pop()); | 10544 return ast_context()->ReturnValue(Pop()); |
10545 | 10545 |
10546 } else { | 10546 } else { |
10547 ASSERT(ast_context()->IsEffect()); | 10547 DCHECK(ast_context()->IsEffect()); |
10548 // In an effect context, we don't need the value of the left subexpression, | 10548 // In an effect context, we don't need the value of the left subexpression, |
10549 // only its control flow and side effects. We need an extra block to | 10549 // only its control flow and side effects. We need an extra block to |
10550 // maintain edge-split form. | 10550 // maintain edge-split form. |
10551 HBasicBlock* empty_block = graph()->CreateBasicBlock(); | 10551 HBasicBlock* empty_block = graph()->CreateBasicBlock(); |
10552 HBasicBlock* right_block = graph()->CreateBasicBlock(); | 10552 HBasicBlock* right_block = graph()->CreateBasicBlock(); |
10553 if (is_logical_and) { | 10553 if (is_logical_and) { |
10554 CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block)); | 10554 CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block)); |
10555 } else { | 10555 } else { |
10556 CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block)); | 10556 CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block)); |
10557 } | 10557 } |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10623 HValue* right) { | 10623 HValue* right) { |
10624 return op == Token::EQ_STRICT && | 10624 return op == Token::EQ_STRICT && |
10625 ((left->IsConstant() && | 10625 ((left->IsConstant() && |
10626 HConstant::cast(left)->handle(isolate)->IsBoolean()) || | 10626 HConstant::cast(left)->handle(isolate)->IsBoolean()) || |
10627 (right->IsConstant() && | 10627 (right->IsConstant() && |
10628 HConstant::cast(right)->handle(isolate)->IsBoolean())); | 10628 HConstant::cast(right)->handle(isolate)->IsBoolean())); |
10629 } | 10629 } |
10630 | 10630 |
10631 | 10631 |
10632 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { | 10632 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
10633 ASSERT(!HasStackOverflow()); | 10633 DCHECK(!HasStackOverflow()); |
10634 ASSERT(current_block() != NULL); | 10634 DCHECK(current_block() != NULL); |
10635 ASSERT(current_block()->HasPredecessor()); | 10635 DCHECK(current_block()->HasPredecessor()); |
10636 | 10636 |
10637 if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); | 10637 if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); |
10638 | 10638 |
10639 // Check for a few fast cases. The AST visiting behavior must be in sync | 10639 // Check for a few fast cases. The AST visiting behavior must be in sync |
10640 // with the full codegen: We don't push both left and right values onto | 10640 // with the full codegen: We don't push both left and right values onto |
10641 // the expression stack when one side is a special-case literal. | 10641 // the expression stack when one side is a special-case literal. |
10642 Expression* sub_expr = NULL; | 10642 Expression* sub_expr = NULL; |
10643 Handle<String> check; | 10643 Handle<String> check; |
10644 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { | 10644 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { |
10645 return HandleLiteralCompareTypeof(expr, sub_expr, check); | 10645 return HandleLiteralCompareTypeof(expr, sub_expr, check); |
10646 } | 10646 } |
10647 if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) { | 10647 if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) { |
10648 return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue); | 10648 return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue); |
10649 } | 10649 } |
10650 if (expr->IsLiteralCompareNull(&sub_expr)) { | 10650 if (expr->IsLiteralCompareNull(&sub_expr)) { |
10651 return HandleLiteralCompareNil(expr, sub_expr, kNullValue); | 10651 return HandleLiteralCompareNil(expr, sub_expr, kNullValue); |
10652 } | 10652 } |
10653 | 10653 |
10654 if (IsClassOfTest(expr)) { | 10654 if (IsClassOfTest(expr)) { |
10655 CallRuntime* call = expr->left()->AsCallRuntime(); | 10655 CallRuntime* call = expr->left()->AsCallRuntime(); |
10656 ASSERT(call->arguments()->length() == 1); | 10656 DCHECK(call->arguments()->length() == 1); |
10657 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 10657 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
10658 HValue* value = Pop(); | 10658 HValue* value = Pop(); |
10659 Literal* literal = expr->right()->AsLiteral(); | 10659 Literal* literal = expr->right()->AsLiteral(); |
10660 Handle<String> rhs = Handle<String>::cast(literal->value()); | 10660 Handle<String> rhs = Handle<String>::cast(literal->value()); |
10661 HClassOfTestAndBranch* instr = New<HClassOfTestAndBranch>(value, rhs); | 10661 HClassOfTestAndBranch* instr = New<HClassOfTestAndBranch>(value, rhs); |
10662 return ast_context()->ReturnControl(instr, expr->id()); | 10662 return ast_context()->ReturnControl(instr, expr->id()); |
10663 } | 10663 } |
10664 | 10664 |
10665 Type* left_type = expr->left()->bounds().lower; | 10665 Type* left_type = expr->left()->bounds().lower; |
10666 Type* right_type = expr->right()->bounds().lower; | 10666 Type* right_type = expr->right()->bounds().lower; |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10857 } | 10857 } |
10858 return result; | 10858 return result; |
10859 } | 10859 } |
10860 } | 10860 } |
10861 } | 10861 } |
10862 | 10862 |
10863 | 10863 |
10864 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, | 10864 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, |
10865 Expression* sub_expr, | 10865 Expression* sub_expr, |
10866 NilValue nil) { | 10866 NilValue nil) { |
10867 ASSERT(!HasStackOverflow()); | 10867 DCHECK(!HasStackOverflow()); |
10868 ASSERT(current_block() != NULL); | 10868 DCHECK(current_block() != NULL); |
10869 ASSERT(current_block()->HasPredecessor()); | 10869 DCHECK(current_block()->HasPredecessor()); |
10870 ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT); | 10870 DCHECK(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT); |
10871 if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); | 10871 if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); |
10872 CHECK_ALIVE(VisitForValue(sub_expr)); | 10872 CHECK_ALIVE(VisitForValue(sub_expr)); |
10873 HValue* value = Pop(); | 10873 HValue* value = Pop(); |
10874 if (expr->op() == Token::EQ_STRICT) { | 10874 if (expr->op() == Token::EQ_STRICT) { |
10875 HConstant* nil_constant = nil == kNullValue | 10875 HConstant* nil_constant = nil == kNullValue |
10876 ? graph()->GetConstantNull() | 10876 ? graph()->GetConstantNull() |
10877 : graph()->GetConstantUndefined(); | 10877 : graph()->GetConstantUndefined(); |
10878 HCompareObjectEqAndBranch* instr = | 10878 HCompareObjectEqAndBranch* instr = |
10879 New<HCompareObjectEqAndBranch>(value, nil_constant); | 10879 New<HCompareObjectEqAndBranch>(value, nil_constant); |
10880 return ast_context()->ReturnControl(instr, expr->id()); | 10880 return ast_context()->ReturnControl(instr, expr->id()); |
10881 } else { | 10881 } else { |
10882 ASSERT_EQ(Token::EQ, expr->op()); | 10882 DCHECK_EQ(Token::EQ, expr->op()); |
10883 Type* type = expr->combined_type()->Is(Type::None()) | 10883 Type* type = expr->combined_type()->Is(Type::None()) |
10884 ? Type::Any(zone()) : expr->combined_type(); | 10884 ? Type::Any(zone()) : expr->combined_type(); |
10885 HIfContinuation continuation; | 10885 HIfContinuation continuation; |
10886 BuildCompareNil(value, type, &continuation); | 10886 BuildCompareNil(value, type, &continuation); |
10887 return ast_context()->ReturnContinuation(&continuation, expr->id()); | 10887 return ast_context()->ReturnContinuation(&continuation, expr->id()); |
10888 } | 10888 } |
10889 } | 10889 } |
10890 | 10890 |
10891 | 10891 |
10892 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { | 10892 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { |
10893 // If we share optimized code between different closures, the | 10893 // If we share optimized code between different closures, the |
10894 // this-function is not a constant, except inside an inlined body. | 10894 // this-function is not a constant, except inside an inlined body. |
10895 if (function_state()->outer() != NULL) { | 10895 if (function_state()->outer() != NULL) { |
10896 return New<HConstant>( | 10896 return New<HConstant>( |
10897 function_state()->compilation_info()->closure()); | 10897 function_state()->compilation_info()->closure()); |
10898 } else { | 10898 } else { |
10899 return New<HThisFunction>(); | 10899 return New<HThisFunction>(); |
10900 } | 10900 } |
10901 } | 10901 } |
10902 | 10902 |
10903 | 10903 |
10904 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( | 10904 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( |
10905 Handle<JSObject> boilerplate_object, | 10905 Handle<JSObject> boilerplate_object, |
10906 AllocationSiteUsageContext* site_context) { | 10906 AllocationSiteUsageContext* site_context) { |
10907 NoObservableSideEffectsScope no_effects(this); | 10907 NoObservableSideEffectsScope no_effects(this); |
10908 InstanceType instance_type = boilerplate_object->map()->instance_type(); | 10908 InstanceType instance_type = boilerplate_object->map()->instance_type(); |
10909 ASSERT(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE); | 10909 DCHECK(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE); |
10910 | 10910 |
10911 HType type = instance_type == JS_ARRAY_TYPE | 10911 HType type = instance_type == JS_ARRAY_TYPE |
10912 ? HType::JSArray() : HType::JSObject(); | 10912 ? HType::JSArray() : HType::JSObject(); |
10913 HValue* object_size_constant = Add<HConstant>( | 10913 HValue* object_size_constant = Add<HConstant>( |
10914 boilerplate_object->map()->instance_size()); | 10914 boilerplate_object->map()->instance_size()); |
10915 | 10915 |
10916 PretenureFlag pretenure_flag = NOT_TENURED; | 10916 PretenureFlag pretenure_flag = NOT_TENURED; |
10917 if (FLAG_allocation_site_pretenuring) { | 10917 if (FLAG_allocation_site_pretenuring) { |
10918 pretenure_flag = site_context->current()->GetPretenureMode(); | 10918 pretenure_flag = site_context->current()->GetPretenureMode(); |
10919 Handle<AllocationSite> site(site_context->current()); | 10919 Handle<AllocationSite> site(site_context->current()); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10974 BuildEmitInObjectProperties(boilerplate_object, object, site_context, | 10974 BuildEmitInObjectProperties(boilerplate_object, object, site_context, |
10975 pretenure_flag); | 10975 pretenure_flag); |
10976 } | 10976 } |
10977 return object; | 10977 return object; |
10978 } | 10978 } |
10979 | 10979 |
10980 | 10980 |
10981 void HOptimizedGraphBuilder::BuildEmitObjectHeader( | 10981 void HOptimizedGraphBuilder::BuildEmitObjectHeader( |
10982 Handle<JSObject> boilerplate_object, | 10982 Handle<JSObject> boilerplate_object, |
10983 HInstruction* object) { | 10983 HInstruction* object) { |
10984 ASSERT(boilerplate_object->properties()->length() == 0); | 10984 DCHECK(boilerplate_object->properties()->length() == 0); |
10985 | 10985 |
10986 Handle<Map> boilerplate_object_map(boilerplate_object->map()); | 10986 Handle<Map> boilerplate_object_map(boilerplate_object->map()); |
10987 AddStoreMapConstant(object, boilerplate_object_map); | 10987 AddStoreMapConstant(object, boilerplate_object_map); |
10988 | 10988 |
10989 Handle<Object> properties_field = | 10989 Handle<Object> properties_field = |
10990 Handle<Object>(boilerplate_object->properties(), isolate()); | 10990 Handle<Object>(boilerplate_object->properties(), isolate()); |
10991 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); | 10991 DCHECK(*properties_field == isolate()->heap()->empty_fixed_array()); |
10992 HInstruction* properties = Add<HConstant>(properties_field); | 10992 HInstruction* properties = Add<HConstant>(properties_field); |
10993 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); | 10993 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); |
10994 Add<HStoreNamedField>(object, access, properties); | 10994 Add<HStoreNamedField>(object, access, properties); |
10995 | 10995 |
10996 if (boilerplate_object->IsJSArray()) { | 10996 if (boilerplate_object->IsJSArray()) { |
10997 Handle<JSArray> boilerplate_array = | 10997 Handle<JSArray> boilerplate_array = |
10998 Handle<JSArray>::cast(boilerplate_object); | 10998 Handle<JSArray>::cast(boilerplate_object); |
10999 Handle<Object> length_field = | 10999 Handle<Object> length_field = |
11000 Handle<Object>(boilerplate_array->length(), isolate()); | 11000 Handle<Object>(boilerplate_array->length(), isolate()); |
11001 HInstruction* length = Add<HConstant>(length_field); | 11001 HInstruction* length = Add<HConstant>(length_field); |
11002 | 11002 |
11003 ASSERT(boilerplate_array->length()->IsSmi()); | 11003 DCHECK(boilerplate_array->length()->IsSmi()); |
11004 Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength( | 11004 Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength( |
11005 boilerplate_array->GetElementsKind()), length); | 11005 boilerplate_array->GetElementsKind()), length); |
11006 } | 11006 } |
11007 } | 11007 } |
11008 | 11008 |
11009 | 11009 |
11010 void HOptimizedGraphBuilder::BuildInitElementsInObjectHeader( | 11010 void HOptimizedGraphBuilder::BuildInitElementsInObjectHeader( |
11011 Handle<JSObject> boilerplate_object, | 11011 Handle<JSObject> boilerplate_object, |
11012 HInstruction* object, | 11012 HInstruction* object, |
11013 HInstruction* object_elements) { | 11013 HInstruction* object_elements) { |
11014 ASSERT(boilerplate_object->properties()->length() == 0); | 11014 DCHECK(boilerplate_object->properties()->length() == 0); |
11015 if (object_elements == NULL) { | 11015 if (object_elements == NULL) { |
11016 Handle<Object> elements_field = | 11016 Handle<Object> elements_field = |
11017 Handle<Object>(boilerplate_object->elements(), isolate()); | 11017 Handle<Object>(boilerplate_object->elements(), isolate()); |
11018 object_elements = Add<HConstant>(elements_field); | 11018 object_elements = Add<HConstant>(elements_field); |
11019 } | 11019 } |
11020 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), | 11020 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
11021 object_elements); | 11021 object_elements); |
11022 } | 11022 } |
11023 | 11023 |
11024 | 11024 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11088 } | 11088 } |
11089 | 11089 |
11090 Add<HStoreNamedField>(object, access, value_instruction); | 11090 Add<HStoreNamedField>(object, access, value_instruction); |
11091 } | 11091 } |
11092 } | 11092 } |
11093 | 11093 |
11094 int inobject_properties = boilerplate_object->map()->inobject_properties(); | 11094 int inobject_properties = boilerplate_object->map()->inobject_properties(); |
11095 HInstruction* value_instruction = | 11095 HInstruction* value_instruction = |
11096 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); | 11096 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); |
11097 for (int i = copied_fields; i < inobject_properties; i++) { | 11097 for (int i = copied_fields; i < inobject_properties; i++) { |
11098 ASSERT(boilerplate_object->IsJSObject()); | 11098 DCHECK(boilerplate_object->IsJSObject()); |
11099 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); | 11099 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); |
11100 HObjectAccess access = | 11100 HObjectAccess access = |
11101 HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset); | 11101 HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset); |
11102 Add<HStoreNamedField>(object, access, value_instruction); | 11102 Add<HStoreNamedField>(object, access, value_instruction); |
11103 } | 11103 } |
11104 } | 11104 } |
11105 | 11105 |
11106 | 11106 |
11107 void HOptimizedGraphBuilder::BuildEmitElements( | 11107 void HOptimizedGraphBuilder::BuildEmitElements( |
11108 Handle<JSObject> boilerplate_object, | 11108 Handle<JSObject> boilerplate_object, |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11168 Add<HLoadKeyed>(boilerplate_elements, key_constant, | 11168 Add<HLoadKeyed>(boilerplate_elements, key_constant, |
11169 static_cast<HValue*>(NULL), kind, | 11169 static_cast<HValue*>(NULL), kind, |
11170 ALLOW_RETURN_HOLE); | 11170 ALLOW_RETURN_HOLE); |
11171 Add<HStoreKeyed>(object_elements, key_constant, value_instruction, kind); | 11171 Add<HStoreKeyed>(object_elements, key_constant, value_instruction, kind); |
11172 } | 11172 } |
11173 } | 11173 } |
11174 } | 11174 } |
11175 | 11175 |
11176 | 11176 |
11177 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 11177 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
11178 ASSERT(!HasStackOverflow()); | 11178 DCHECK(!HasStackOverflow()); |
11179 ASSERT(current_block() != NULL); | 11179 DCHECK(current_block() != NULL); |
11180 ASSERT(current_block()->HasPredecessor()); | 11180 DCHECK(current_block()->HasPredecessor()); |
11181 HInstruction* instr = BuildThisFunction(); | 11181 HInstruction* instr = BuildThisFunction(); |
11182 return ast_context()->ReturnInstruction(instr, expr->id()); | 11182 return ast_context()->ReturnInstruction(instr, expr->id()); |
11183 } | 11183 } |
11184 | 11184 |
11185 | 11185 |
11186 void HOptimizedGraphBuilder::VisitDeclarations( | 11186 void HOptimizedGraphBuilder::VisitDeclarations( |
11187 ZoneList<Declaration*>* declarations) { | 11187 ZoneList<Declaration*>* declarations) { |
11188 ASSERT(globals_.is_empty()); | 11188 DCHECK(globals_.is_empty()); |
11189 AstVisitor::VisitDeclarations(declarations); | 11189 AstVisitor::VisitDeclarations(declarations); |
11190 if (!globals_.is_empty()) { | 11190 if (!globals_.is_empty()) { |
11191 Handle<FixedArray> array = | 11191 Handle<FixedArray> array = |
11192 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); | 11192 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); |
11193 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); | 11193 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); |
11194 int flags = DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) | | 11194 int flags = DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) | |
11195 DeclareGlobalsNativeFlag::encode(current_info()->is_native()) | | 11195 DeclareGlobalsNativeFlag::encode(current_info()->is_native()) | |
11196 DeclareGlobalsStrictMode::encode(current_info()->strict_mode()); | 11196 DeclareGlobalsStrictMode::encode(current_info()->strict_mode()); |
11197 Add<HDeclareGlobals>(array, flags); | 11197 Add<HDeclareGlobals>(array, flags); |
11198 globals_.Rewind(0); | 11198 globals_.Rewind(0); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11314 | 11314 |
11315 | 11315 |
11316 void HOptimizedGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) { | 11316 void HOptimizedGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) { |
11317 UNREACHABLE(); | 11317 UNREACHABLE(); |
11318 } | 11318 } |
11319 | 11319 |
11320 | 11320 |
11321 // Generators for inline runtime functions. | 11321 // Generators for inline runtime functions. |
11322 // Support for types. | 11322 // Support for types. |
11323 void HOptimizedGraphBuilder::GenerateIsSmi(CallRuntime* call) { | 11323 void HOptimizedGraphBuilder::GenerateIsSmi(CallRuntime* call) { |
11324 ASSERT(call->arguments()->length() == 1); | 11324 DCHECK(call->arguments()->length() == 1); |
11325 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11325 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11326 HValue* value = Pop(); | 11326 HValue* value = Pop(); |
11327 HIsSmiAndBranch* result = New<HIsSmiAndBranch>(value); | 11327 HIsSmiAndBranch* result = New<HIsSmiAndBranch>(value); |
11328 return ast_context()->ReturnControl(result, call->id()); | 11328 return ast_context()->ReturnControl(result, call->id()); |
11329 } | 11329 } |
11330 | 11330 |
11331 | 11331 |
11332 void HOptimizedGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { | 11332 void HOptimizedGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { |
11333 ASSERT(call->arguments()->length() == 1); | 11333 DCHECK(call->arguments()->length() == 1); |
11334 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11334 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11335 HValue* value = Pop(); | 11335 HValue* value = Pop(); |
11336 HHasInstanceTypeAndBranch* result = | 11336 HHasInstanceTypeAndBranch* result = |
11337 New<HHasInstanceTypeAndBranch>(value, | 11337 New<HHasInstanceTypeAndBranch>(value, |
11338 FIRST_SPEC_OBJECT_TYPE, | 11338 FIRST_SPEC_OBJECT_TYPE, |
11339 LAST_SPEC_OBJECT_TYPE); | 11339 LAST_SPEC_OBJECT_TYPE); |
11340 return ast_context()->ReturnControl(result, call->id()); | 11340 return ast_context()->ReturnControl(result, call->id()); |
11341 } | 11341 } |
11342 | 11342 |
11343 | 11343 |
11344 void HOptimizedGraphBuilder::GenerateIsFunction(CallRuntime* call) { | 11344 void HOptimizedGraphBuilder::GenerateIsFunction(CallRuntime* call) { |
11345 ASSERT(call->arguments()->length() == 1); | 11345 DCHECK(call->arguments()->length() == 1); |
11346 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11346 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11347 HValue* value = Pop(); | 11347 HValue* value = Pop(); |
11348 HHasInstanceTypeAndBranch* result = | 11348 HHasInstanceTypeAndBranch* result = |
11349 New<HHasInstanceTypeAndBranch>(value, JS_FUNCTION_TYPE); | 11349 New<HHasInstanceTypeAndBranch>(value, JS_FUNCTION_TYPE); |
11350 return ast_context()->ReturnControl(result, call->id()); | 11350 return ast_context()->ReturnControl(result, call->id()); |
11351 } | 11351 } |
11352 | 11352 |
11353 | 11353 |
11354 void HOptimizedGraphBuilder::GenerateIsMinusZero(CallRuntime* call) { | 11354 void HOptimizedGraphBuilder::GenerateIsMinusZero(CallRuntime* call) { |
11355 ASSERT(call->arguments()->length() == 1); | 11355 DCHECK(call->arguments()->length() == 1); |
11356 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11356 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11357 HValue* value = Pop(); | 11357 HValue* value = Pop(); |
11358 HCompareMinusZeroAndBranch* result = New<HCompareMinusZeroAndBranch>(value); | 11358 HCompareMinusZeroAndBranch* result = New<HCompareMinusZeroAndBranch>(value); |
11359 return ast_context()->ReturnControl(result, call->id()); | 11359 return ast_context()->ReturnControl(result, call->id()); |
11360 } | 11360 } |
11361 | 11361 |
11362 | 11362 |
11363 void HOptimizedGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) { | 11363 void HOptimizedGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) { |
11364 ASSERT(call->arguments()->length() == 1); | 11364 DCHECK(call->arguments()->length() == 1); |
11365 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11365 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11366 HValue* value = Pop(); | 11366 HValue* value = Pop(); |
11367 HHasCachedArrayIndexAndBranch* result = | 11367 HHasCachedArrayIndexAndBranch* result = |
11368 New<HHasCachedArrayIndexAndBranch>(value); | 11368 New<HHasCachedArrayIndexAndBranch>(value); |
11369 return ast_context()->ReturnControl(result, call->id()); | 11369 return ast_context()->ReturnControl(result, call->id()); |
11370 } | 11370 } |
11371 | 11371 |
11372 | 11372 |
11373 void HOptimizedGraphBuilder::GenerateIsArray(CallRuntime* call) { | 11373 void HOptimizedGraphBuilder::GenerateIsArray(CallRuntime* call) { |
11374 ASSERT(call->arguments()->length() == 1); | 11374 DCHECK(call->arguments()->length() == 1); |
11375 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11375 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11376 HValue* value = Pop(); | 11376 HValue* value = Pop(); |
11377 HHasInstanceTypeAndBranch* result = | 11377 HHasInstanceTypeAndBranch* result = |
11378 New<HHasInstanceTypeAndBranch>(value, JS_ARRAY_TYPE); | 11378 New<HHasInstanceTypeAndBranch>(value, JS_ARRAY_TYPE); |
11379 return ast_context()->ReturnControl(result, call->id()); | 11379 return ast_context()->ReturnControl(result, call->id()); |
11380 } | 11380 } |
11381 | 11381 |
11382 | 11382 |
11383 void HOptimizedGraphBuilder::GenerateIsRegExp(CallRuntime* call) { | 11383 void HOptimizedGraphBuilder::GenerateIsRegExp(CallRuntime* call) { |
11384 ASSERT(call->arguments()->length() == 1); | 11384 DCHECK(call->arguments()->length() == 1); |
11385 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11385 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11386 HValue* value = Pop(); | 11386 HValue* value = Pop(); |
11387 HHasInstanceTypeAndBranch* result = | 11387 HHasInstanceTypeAndBranch* result = |
11388 New<HHasInstanceTypeAndBranch>(value, JS_REGEXP_TYPE); | 11388 New<HHasInstanceTypeAndBranch>(value, JS_REGEXP_TYPE); |
11389 return ast_context()->ReturnControl(result, call->id()); | 11389 return ast_context()->ReturnControl(result, call->id()); |
11390 } | 11390 } |
11391 | 11391 |
11392 | 11392 |
11393 void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) { | 11393 void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) { |
11394 ASSERT(call->arguments()->length() == 1); | 11394 DCHECK(call->arguments()->length() == 1); |
11395 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11395 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11396 HValue* value = Pop(); | 11396 HValue* value = Pop(); |
11397 HIsObjectAndBranch* result = New<HIsObjectAndBranch>(value); | 11397 HIsObjectAndBranch* result = New<HIsObjectAndBranch>(value); |
11398 return ast_context()->ReturnControl(result, call->id()); | 11398 return ast_context()->ReturnControl(result, call->id()); |
11399 } | 11399 } |
11400 | 11400 |
11401 | 11401 |
11402 void HOptimizedGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { | 11402 void HOptimizedGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { |
11403 return Bailout(kInlinedRuntimeFunctionIsNonNegativeSmi); | 11403 return Bailout(kInlinedRuntimeFunctionIsNonNegativeSmi); |
11404 } | 11404 } |
11405 | 11405 |
11406 | 11406 |
11407 void HOptimizedGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { | 11407 void HOptimizedGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { |
11408 ASSERT(call->arguments()->length() == 1); | 11408 DCHECK(call->arguments()->length() == 1); |
11409 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11409 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11410 HValue* value = Pop(); | 11410 HValue* value = Pop(); |
11411 HIsUndetectableAndBranch* result = New<HIsUndetectableAndBranch>(value); | 11411 HIsUndetectableAndBranch* result = New<HIsUndetectableAndBranch>(value); |
11412 return ast_context()->ReturnControl(result, call->id()); | 11412 return ast_context()->ReturnControl(result, call->id()); |
11413 } | 11413 } |
11414 | 11414 |
11415 | 11415 |
11416 void HOptimizedGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( | 11416 void HOptimizedGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( |
11417 CallRuntime* call) { | 11417 CallRuntime* call) { |
11418 return Bailout(kInlinedRuntimeFunctionIsStringWrapperSafeForDefaultValueOf); | 11418 return Bailout(kInlinedRuntimeFunctionIsStringWrapperSafeForDefaultValueOf); |
11419 } | 11419 } |
11420 | 11420 |
11421 | 11421 |
11422 // Support for construct call checks. | 11422 // Support for construct call checks. |
11423 void HOptimizedGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { | 11423 void HOptimizedGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { |
11424 ASSERT(call->arguments()->length() == 0); | 11424 DCHECK(call->arguments()->length() == 0); |
11425 if (function_state()->outer() != NULL) { | 11425 if (function_state()->outer() != NULL) { |
11426 // We are generating graph for inlined function. | 11426 // We are generating graph for inlined function. |
11427 HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN | 11427 HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN |
11428 ? graph()->GetConstantTrue() | 11428 ? graph()->GetConstantTrue() |
11429 : graph()->GetConstantFalse(); | 11429 : graph()->GetConstantFalse(); |
11430 return ast_context()->ReturnValue(value); | 11430 return ast_context()->ReturnValue(value); |
11431 } else { | 11431 } else { |
11432 return ast_context()->ReturnControl(New<HIsConstructCallAndBranch>(), | 11432 return ast_context()->ReturnControl(New<HIsConstructCallAndBranch>(), |
11433 call->id()); | 11433 call->id()); |
11434 } | 11434 } |
11435 } | 11435 } |
11436 | 11436 |
11437 | 11437 |
11438 // Support for arguments.length and arguments[?]. | 11438 // Support for arguments.length and arguments[?]. |
11439 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { | 11439 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { |
11440 ASSERT(call->arguments()->length() == 0); | 11440 DCHECK(call->arguments()->length() == 0); |
11441 HInstruction* result = NULL; | 11441 HInstruction* result = NULL; |
11442 if (function_state()->outer() == NULL) { | 11442 if (function_state()->outer() == NULL) { |
11443 HInstruction* elements = Add<HArgumentsElements>(false); | 11443 HInstruction* elements = Add<HArgumentsElements>(false); |
11444 result = New<HArgumentsLength>(elements); | 11444 result = New<HArgumentsLength>(elements); |
11445 } else { | 11445 } else { |
11446 // Number of arguments without receiver. | 11446 // Number of arguments without receiver. |
11447 int argument_count = environment()-> | 11447 int argument_count = environment()-> |
11448 arguments_environment()->parameter_count() - 1; | 11448 arguments_environment()->parameter_count() - 1; |
11449 result = New<HConstant>(argument_count); | 11449 result = New<HConstant>(argument_count); |
11450 } | 11450 } |
11451 return ast_context()->ReturnInstruction(result, call->id()); | 11451 return ast_context()->ReturnInstruction(result, call->id()); |
11452 } | 11452 } |
11453 | 11453 |
11454 | 11454 |
11455 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) { | 11455 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) { |
11456 ASSERT(call->arguments()->length() == 1); | 11456 DCHECK(call->arguments()->length() == 1); |
11457 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11457 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11458 HValue* index = Pop(); | 11458 HValue* index = Pop(); |
11459 HInstruction* result = NULL; | 11459 HInstruction* result = NULL; |
11460 if (function_state()->outer() == NULL) { | 11460 if (function_state()->outer() == NULL) { |
11461 HInstruction* elements = Add<HArgumentsElements>(false); | 11461 HInstruction* elements = Add<HArgumentsElements>(false); |
11462 HInstruction* length = Add<HArgumentsLength>(elements); | 11462 HInstruction* length = Add<HArgumentsLength>(elements); |
11463 HInstruction* checked_index = Add<HBoundsCheck>(index, length); | 11463 HInstruction* checked_index = Add<HBoundsCheck>(index, length); |
11464 result = New<HAccessArgumentsAt>(elements, length, checked_index); | 11464 result = New<HAccessArgumentsAt>(elements, length, checked_index); |
11465 } else { | 11465 } else { |
11466 EnsureArgumentsArePushedForAccess(); | 11466 EnsureArgumentsArePushedForAccess(); |
(...skipping 12 matching lines...) Expand all Loading... |
11479 | 11479 |
11480 // Support for accessing the class and value fields of an object. | 11480 // Support for accessing the class and value fields of an object. |
11481 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) { | 11481 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) { |
11482 // The special form detected by IsClassOfTest is detected before we get here | 11482 // The special form detected by IsClassOfTest is detected before we get here |
11483 // and does not cause a bailout. | 11483 // and does not cause a bailout. |
11484 return Bailout(kInlinedRuntimeFunctionClassOf); | 11484 return Bailout(kInlinedRuntimeFunctionClassOf); |
11485 } | 11485 } |
11486 | 11486 |
11487 | 11487 |
11488 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) { | 11488 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) { |
11489 ASSERT(call->arguments()->length() == 1); | 11489 DCHECK(call->arguments()->length() == 1); |
11490 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11490 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11491 HValue* object = Pop(); | 11491 HValue* object = Pop(); |
11492 | 11492 |
11493 IfBuilder if_objectisvalue(this); | 11493 IfBuilder if_objectisvalue(this); |
11494 HValue* objectisvalue = if_objectisvalue.If<HHasInstanceTypeAndBranch>( | 11494 HValue* objectisvalue = if_objectisvalue.If<HHasInstanceTypeAndBranch>( |
11495 object, JS_VALUE_TYPE); | 11495 object, JS_VALUE_TYPE); |
11496 if_objectisvalue.Then(); | 11496 if_objectisvalue.Then(); |
11497 { | 11497 { |
11498 // Return the actual value. | 11498 // Return the actual value. |
11499 Push(Add<HLoadNamedField>( | 11499 Push(Add<HLoadNamedField>( |
11500 object, objectisvalue, | 11500 object, objectisvalue, |
11501 HObjectAccess::ForObservableJSObjectOffset( | 11501 HObjectAccess::ForObservableJSObjectOffset( |
11502 JSValue::kValueOffset))); | 11502 JSValue::kValueOffset))); |
11503 Add<HSimulate>(call->id(), FIXED_SIMULATE); | 11503 Add<HSimulate>(call->id(), FIXED_SIMULATE); |
11504 } | 11504 } |
11505 if_objectisvalue.Else(); | 11505 if_objectisvalue.Else(); |
11506 { | 11506 { |
11507 // If the object is not a value return the object. | 11507 // If the object is not a value return the object. |
11508 Push(object); | 11508 Push(object); |
11509 Add<HSimulate>(call->id(), FIXED_SIMULATE); | 11509 Add<HSimulate>(call->id(), FIXED_SIMULATE); |
11510 } | 11510 } |
11511 if_objectisvalue.End(); | 11511 if_objectisvalue.End(); |
11512 return ast_context()->ReturnValue(Pop()); | 11512 return ast_context()->ReturnValue(Pop()); |
11513 } | 11513 } |
11514 | 11514 |
11515 | 11515 |
11516 void HOptimizedGraphBuilder::GenerateDateField(CallRuntime* call) { | 11516 void HOptimizedGraphBuilder::GenerateDateField(CallRuntime* call) { |
11517 ASSERT(call->arguments()->length() == 2); | 11517 DCHECK(call->arguments()->length() == 2); |
11518 ASSERT_NE(NULL, call->arguments()->at(1)->AsLiteral()); | 11518 DCHECK_NE(NULL, call->arguments()->at(1)->AsLiteral()); |
11519 Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->value())); | 11519 Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->value())); |
11520 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11520 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11521 HValue* date = Pop(); | 11521 HValue* date = Pop(); |
11522 HDateField* result = New<HDateField>(date, index); | 11522 HDateField* result = New<HDateField>(date, index); |
11523 return ast_context()->ReturnInstruction(result, call->id()); | 11523 return ast_context()->ReturnInstruction(result, call->id()); |
11524 } | 11524 } |
11525 | 11525 |
11526 | 11526 |
11527 void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar( | 11527 void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar( |
11528 CallRuntime* call) { | 11528 CallRuntime* call) { |
11529 ASSERT(call->arguments()->length() == 3); | 11529 DCHECK(call->arguments()->length() == 3); |
11530 // We need to follow the evaluation order of full codegen. | 11530 // We need to follow the evaluation order of full codegen. |
11531 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 11531 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
11532 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); | 11532 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); |
11533 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11533 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11534 HValue* string = Pop(); | 11534 HValue* string = Pop(); |
11535 HValue* value = Pop(); | 11535 HValue* value = Pop(); |
11536 HValue* index = Pop(); | 11536 HValue* index = Pop(); |
11537 Add<HSeqStringSetChar>(String::ONE_BYTE_ENCODING, string, | 11537 Add<HSeqStringSetChar>(String::ONE_BYTE_ENCODING, string, |
11538 index, value); | 11538 index, value); |
11539 Add<HSimulate>(call->id(), FIXED_SIMULATE); | 11539 Add<HSimulate>(call->id(), FIXED_SIMULATE); |
11540 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 11540 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
11541 } | 11541 } |
11542 | 11542 |
11543 | 11543 |
11544 void HOptimizedGraphBuilder::GenerateTwoByteSeqStringSetChar( | 11544 void HOptimizedGraphBuilder::GenerateTwoByteSeqStringSetChar( |
11545 CallRuntime* call) { | 11545 CallRuntime* call) { |
11546 ASSERT(call->arguments()->length() == 3); | 11546 DCHECK(call->arguments()->length() == 3); |
11547 // We need to follow the evaluation order of full codegen. | 11547 // We need to follow the evaluation order of full codegen. |
11548 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 11548 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
11549 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); | 11549 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); |
11550 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11550 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11551 HValue* string = Pop(); | 11551 HValue* string = Pop(); |
11552 HValue* value = Pop(); | 11552 HValue* value = Pop(); |
11553 HValue* index = Pop(); | 11553 HValue* index = Pop(); |
11554 Add<HSeqStringSetChar>(String::TWO_BYTE_ENCODING, string, | 11554 Add<HSeqStringSetChar>(String::TWO_BYTE_ENCODING, string, |
11555 index, value); | 11555 index, value); |
11556 Add<HSimulate>(call->id(), FIXED_SIMULATE); | 11556 Add<HSimulate>(call->id(), FIXED_SIMULATE); |
11557 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 11557 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
11558 } | 11558 } |
11559 | 11559 |
11560 | 11560 |
11561 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) { | 11561 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) { |
11562 ASSERT(call->arguments()->length() == 2); | 11562 DCHECK(call->arguments()->length() == 2); |
11563 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11563 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11564 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 11564 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
11565 HValue* value = Pop(); | 11565 HValue* value = Pop(); |
11566 HValue* object = Pop(); | 11566 HValue* object = Pop(); |
11567 | 11567 |
11568 // Check if object is a JSValue. | 11568 // Check if object is a JSValue. |
11569 IfBuilder if_objectisvalue(this); | 11569 IfBuilder if_objectisvalue(this); |
11570 if_objectisvalue.If<HHasInstanceTypeAndBranch>(object, JS_VALUE_TYPE); | 11570 if_objectisvalue.If<HHasInstanceTypeAndBranch>(object, JS_VALUE_TYPE); |
11571 if_objectisvalue.Then(); | 11571 if_objectisvalue.Then(); |
11572 { | 11572 { |
(...skipping 17 matching lines...) Expand all Loading... |
11590 if_objectisvalue.End(); | 11590 if_objectisvalue.End(); |
11591 if (!ast_context()->IsEffect()) { | 11591 if (!ast_context()->IsEffect()) { |
11592 Drop(1); | 11592 Drop(1); |
11593 } | 11593 } |
11594 return ast_context()->ReturnValue(value); | 11594 return ast_context()->ReturnValue(value); |
11595 } | 11595 } |
11596 | 11596 |
11597 | 11597 |
11598 // Fast support for charCodeAt(n). | 11598 // Fast support for charCodeAt(n). |
11599 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { | 11599 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { |
11600 ASSERT(call->arguments()->length() == 2); | 11600 DCHECK(call->arguments()->length() == 2); |
11601 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11601 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11602 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 11602 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
11603 HValue* index = Pop(); | 11603 HValue* index = Pop(); |
11604 HValue* string = Pop(); | 11604 HValue* string = Pop(); |
11605 HInstruction* result = BuildStringCharCodeAt(string, index); | 11605 HInstruction* result = BuildStringCharCodeAt(string, index); |
11606 return ast_context()->ReturnInstruction(result, call->id()); | 11606 return ast_context()->ReturnInstruction(result, call->id()); |
11607 } | 11607 } |
11608 | 11608 |
11609 | 11609 |
11610 // Fast support for string.charAt(n) and string[n]. | 11610 // Fast support for string.charAt(n) and string[n]. |
11611 void HOptimizedGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { | 11611 void HOptimizedGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { |
11612 ASSERT(call->arguments()->length() == 1); | 11612 DCHECK(call->arguments()->length() == 1); |
11613 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11613 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11614 HValue* char_code = Pop(); | 11614 HValue* char_code = Pop(); |
11615 HInstruction* result = NewUncasted<HStringCharFromCode>(char_code); | 11615 HInstruction* result = NewUncasted<HStringCharFromCode>(char_code); |
11616 return ast_context()->ReturnInstruction(result, call->id()); | 11616 return ast_context()->ReturnInstruction(result, call->id()); |
11617 } | 11617 } |
11618 | 11618 |
11619 | 11619 |
11620 // Fast support for string.charAt(n) and string[n]. | 11620 // Fast support for string.charAt(n) and string[n]. |
11621 void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) { | 11621 void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) { |
11622 ASSERT(call->arguments()->length() == 2); | 11622 DCHECK(call->arguments()->length() == 2); |
11623 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11623 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11624 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 11624 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
11625 HValue* index = Pop(); | 11625 HValue* index = Pop(); |
11626 HValue* string = Pop(); | 11626 HValue* string = Pop(); |
11627 HInstruction* char_code = BuildStringCharCodeAt(string, index); | 11627 HInstruction* char_code = BuildStringCharCodeAt(string, index); |
11628 AddInstruction(char_code); | 11628 AddInstruction(char_code); |
11629 HInstruction* result = NewUncasted<HStringCharFromCode>(char_code); | 11629 HInstruction* result = NewUncasted<HStringCharFromCode>(char_code); |
11630 return ast_context()->ReturnInstruction(result, call->id()); | 11630 return ast_context()->ReturnInstruction(result, call->id()); |
11631 } | 11631 } |
11632 | 11632 |
11633 | 11633 |
11634 // Fast support for object equality testing. | 11634 // Fast support for object equality testing. |
11635 void HOptimizedGraphBuilder::GenerateObjectEquals(CallRuntime* call) { | 11635 void HOptimizedGraphBuilder::GenerateObjectEquals(CallRuntime* call) { |
11636 ASSERT(call->arguments()->length() == 2); | 11636 DCHECK(call->arguments()->length() == 2); |
11637 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11637 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11638 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 11638 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
11639 HValue* right = Pop(); | 11639 HValue* right = Pop(); |
11640 HValue* left = Pop(); | 11640 HValue* left = Pop(); |
11641 HCompareObjectEqAndBranch* result = | 11641 HCompareObjectEqAndBranch* result = |
11642 New<HCompareObjectEqAndBranch>(left, right); | 11642 New<HCompareObjectEqAndBranch>(left, right); |
11643 return ast_context()->ReturnControl(result, call->id()); | 11643 return ast_context()->ReturnControl(result, call->id()); |
11644 } | 11644 } |
11645 | 11645 |
11646 | 11646 |
11647 // Fast support for StringAdd. | 11647 // Fast support for StringAdd. |
11648 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { | 11648 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { |
11649 ASSERT_EQ(2, call->arguments()->length()); | 11649 DCHECK_EQ(2, call->arguments()->length()); |
11650 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11650 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11651 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 11651 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
11652 HValue* right = Pop(); | 11652 HValue* right = Pop(); |
11653 HValue* left = Pop(); | 11653 HValue* left = Pop(); |
11654 HInstruction* result = NewUncasted<HStringAdd>(left, right); | 11654 HInstruction* result = NewUncasted<HStringAdd>(left, right); |
11655 return ast_context()->ReturnInstruction(result, call->id()); | 11655 return ast_context()->ReturnInstruction(result, call->id()); |
11656 } | 11656 } |
11657 | 11657 |
11658 | 11658 |
11659 // Fast support for SubString. | 11659 // Fast support for SubString. |
11660 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { | 11660 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { |
11661 ASSERT_EQ(3, call->arguments()->length()); | 11661 DCHECK_EQ(3, call->arguments()->length()); |
11662 CHECK_ALIVE(VisitExpressions(call->arguments())); | 11662 CHECK_ALIVE(VisitExpressions(call->arguments())); |
11663 PushArgumentsFromEnvironment(call->arguments()->length()); | 11663 PushArgumentsFromEnvironment(call->arguments()->length()); |
11664 HCallStub* result = New<HCallStub>(CodeStub::SubString, 3); | 11664 HCallStub* result = New<HCallStub>(CodeStub::SubString, 3); |
11665 return ast_context()->ReturnInstruction(result, call->id()); | 11665 return ast_context()->ReturnInstruction(result, call->id()); |
11666 } | 11666 } |
11667 | 11667 |
11668 | 11668 |
11669 // Fast support for StringCompare. | 11669 // Fast support for StringCompare. |
11670 void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) { | 11670 void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) { |
11671 ASSERT_EQ(2, call->arguments()->length()); | 11671 DCHECK_EQ(2, call->arguments()->length()); |
11672 CHECK_ALIVE(VisitExpressions(call->arguments())); | 11672 CHECK_ALIVE(VisitExpressions(call->arguments())); |
11673 PushArgumentsFromEnvironment(call->arguments()->length()); | 11673 PushArgumentsFromEnvironment(call->arguments()->length()); |
11674 HCallStub* result = New<HCallStub>(CodeStub::StringCompare, 2); | 11674 HCallStub* result = New<HCallStub>(CodeStub::StringCompare, 2); |
11675 return ast_context()->ReturnInstruction(result, call->id()); | 11675 return ast_context()->ReturnInstruction(result, call->id()); |
11676 } | 11676 } |
11677 | 11677 |
11678 | 11678 |
11679 // Support for direct calls from JavaScript to native RegExp code. | 11679 // Support for direct calls from JavaScript to native RegExp code. |
11680 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) { | 11680 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) { |
11681 ASSERT_EQ(4, call->arguments()->length()); | 11681 DCHECK_EQ(4, call->arguments()->length()); |
11682 CHECK_ALIVE(VisitExpressions(call->arguments())); | 11682 CHECK_ALIVE(VisitExpressions(call->arguments())); |
11683 PushArgumentsFromEnvironment(call->arguments()->length()); | 11683 PushArgumentsFromEnvironment(call->arguments()->length()); |
11684 HCallStub* result = New<HCallStub>(CodeStub::RegExpExec, 4); | 11684 HCallStub* result = New<HCallStub>(CodeStub::RegExpExec, 4); |
11685 return ast_context()->ReturnInstruction(result, call->id()); | 11685 return ast_context()->ReturnInstruction(result, call->id()); |
11686 } | 11686 } |
11687 | 11687 |
11688 | 11688 |
11689 void HOptimizedGraphBuilder::GenerateDoubleLo(CallRuntime* call) { | 11689 void HOptimizedGraphBuilder::GenerateDoubleLo(CallRuntime* call) { |
11690 ASSERT_EQ(1, call->arguments()->length()); | 11690 DCHECK_EQ(1, call->arguments()->length()); |
11691 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11691 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11692 HValue* value = Pop(); | 11692 HValue* value = Pop(); |
11693 HInstruction* result = NewUncasted<HDoubleBits>(value, HDoubleBits::LOW); | 11693 HInstruction* result = NewUncasted<HDoubleBits>(value, HDoubleBits::LOW); |
11694 return ast_context()->ReturnInstruction(result, call->id()); | 11694 return ast_context()->ReturnInstruction(result, call->id()); |
11695 } | 11695 } |
11696 | 11696 |
11697 | 11697 |
11698 void HOptimizedGraphBuilder::GenerateDoubleHi(CallRuntime* call) { | 11698 void HOptimizedGraphBuilder::GenerateDoubleHi(CallRuntime* call) { |
11699 ASSERT_EQ(1, call->arguments()->length()); | 11699 DCHECK_EQ(1, call->arguments()->length()); |
11700 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11700 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11701 HValue* value = Pop(); | 11701 HValue* value = Pop(); |
11702 HInstruction* result = NewUncasted<HDoubleBits>(value, HDoubleBits::HIGH); | 11702 HInstruction* result = NewUncasted<HDoubleBits>(value, HDoubleBits::HIGH); |
11703 return ast_context()->ReturnInstruction(result, call->id()); | 11703 return ast_context()->ReturnInstruction(result, call->id()); |
11704 } | 11704 } |
11705 | 11705 |
11706 | 11706 |
11707 void HOptimizedGraphBuilder::GenerateConstructDouble(CallRuntime* call) { | 11707 void HOptimizedGraphBuilder::GenerateConstructDouble(CallRuntime* call) { |
11708 ASSERT_EQ(2, call->arguments()->length()); | 11708 DCHECK_EQ(2, call->arguments()->length()); |
11709 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11709 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11710 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 11710 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
11711 HValue* lo = Pop(); | 11711 HValue* lo = Pop(); |
11712 HValue* hi = Pop(); | 11712 HValue* hi = Pop(); |
11713 HInstruction* result = NewUncasted<HConstructDouble>(hi, lo); | 11713 HInstruction* result = NewUncasted<HConstructDouble>(hi, lo); |
11714 return ast_context()->ReturnInstruction(result, call->id()); | 11714 return ast_context()->ReturnInstruction(result, call->id()); |
11715 } | 11715 } |
11716 | 11716 |
11717 | 11717 |
11718 // Construct a RegExp exec result with two in-object properties. | 11718 // Construct a RegExp exec result with two in-object properties. |
11719 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { | 11719 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { |
11720 ASSERT_EQ(3, call->arguments()->length()); | 11720 DCHECK_EQ(3, call->arguments()->length()); |
11721 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11721 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11722 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 11722 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
11723 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); | 11723 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); |
11724 HValue* input = Pop(); | 11724 HValue* input = Pop(); |
11725 HValue* index = Pop(); | 11725 HValue* index = Pop(); |
11726 HValue* length = Pop(); | 11726 HValue* length = Pop(); |
11727 HValue* result = BuildRegExpConstructResult(length, index, input); | 11727 HValue* result = BuildRegExpConstructResult(length, index, input); |
11728 return ast_context()->ReturnValue(result); | 11728 return ast_context()->ReturnValue(result); |
11729 } | 11729 } |
11730 | 11730 |
11731 | 11731 |
11732 // Support for fast native caches. | 11732 // Support for fast native caches. |
11733 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { | 11733 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { |
11734 return Bailout(kInlinedRuntimeFunctionGetFromCache); | 11734 return Bailout(kInlinedRuntimeFunctionGetFromCache); |
11735 } | 11735 } |
11736 | 11736 |
11737 | 11737 |
11738 // Fast support for number to string. | 11738 // Fast support for number to string. |
11739 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { | 11739 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { |
11740 ASSERT_EQ(1, call->arguments()->length()); | 11740 DCHECK_EQ(1, call->arguments()->length()); |
11741 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11741 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11742 HValue* number = Pop(); | 11742 HValue* number = Pop(); |
11743 HValue* result = BuildNumberToString(number, Type::Any(zone())); | 11743 HValue* result = BuildNumberToString(number, Type::Any(zone())); |
11744 return ast_context()->ReturnValue(result); | 11744 return ast_context()->ReturnValue(result); |
11745 } | 11745 } |
11746 | 11746 |
11747 | 11747 |
11748 // Fast call for custom callbacks. | 11748 // Fast call for custom callbacks. |
11749 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { | 11749 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { |
11750 // 1 ~ The function to call is not itself an argument to the call. | 11750 // 1 ~ The function to call is not itself an argument to the call. |
11751 int arg_count = call->arguments()->length() - 1; | 11751 int arg_count = call->arguments()->length() - 1; |
11752 ASSERT(arg_count >= 1); // There's always at least a receiver. | 11752 DCHECK(arg_count >= 1); // There's always at least a receiver. |
11753 | 11753 |
11754 CHECK_ALIVE(VisitExpressions(call->arguments())); | 11754 CHECK_ALIVE(VisitExpressions(call->arguments())); |
11755 // The function is the last argument | 11755 // The function is the last argument |
11756 HValue* function = Pop(); | 11756 HValue* function = Pop(); |
11757 // Push the arguments to the stack | 11757 // Push the arguments to the stack |
11758 PushArgumentsFromEnvironment(arg_count); | 11758 PushArgumentsFromEnvironment(arg_count); |
11759 | 11759 |
11760 IfBuilder if_is_jsfunction(this); | 11760 IfBuilder if_is_jsfunction(this); |
11761 if_is_jsfunction.If<HHasInstanceTypeAndBranch>(function, JS_FUNCTION_TYPE); | 11761 if_is_jsfunction.If<HHasInstanceTypeAndBranch>(function, JS_FUNCTION_TYPE); |
11762 | 11762 |
(...skipping 23 matching lines...) Expand all Loading... |
11786 // 'undefined' (as we do not have the call result anymore). | 11786 // 'undefined' (as we do not have the call result anymore). |
11787 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 11787 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
11788 } else { | 11788 } else { |
11789 return ast_context()->ReturnValue(Pop()); | 11789 return ast_context()->ReturnValue(Pop()); |
11790 } | 11790 } |
11791 } | 11791 } |
11792 | 11792 |
11793 | 11793 |
11794 // Fast call to math functions. | 11794 // Fast call to math functions. |
11795 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) { | 11795 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) { |
11796 ASSERT_EQ(2, call->arguments()->length()); | 11796 DCHECK_EQ(2, call->arguments()->length()); |
11797 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11797 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11798 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 11798 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
11799 HValue* right = Pop(); | 11799 HValue* right = Pop(); |
11800 HValue* left = Pop(); | 11800 HValue* left = Pop(); |
11801 HInstruction* result = NewUncasted<HPower>(left, right); | 11801 HInstruction* result = NewUncasted<HPower>(left, right); |
11802 return ast_context()->ReturnInstruction(result, call->id()); | 11802 return ast_context()->ReturnInstruction(result, call->id()); |
11803 } | 11803 } |
11804 | 11804 |
11805 | 11805 |
11806 void HOptimizedGraphBuilder::GenerateMathLogRT(CallRuntime* call) { | 11806 void HOptimizedGraphBuilder::GenerateMathLogRT(CallRuntime* call) { |
11807 ASSERT(call->arguments()->length() == 1); | 11807 DCHECK(call->arguments()->length() == 1); |
11808 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11808 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11809 HValue* value = Pop(); | 11809 HValue* value = Pop(); |
11810 HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathLog); | 11810 HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathLog); |
11811 return ast_context()->ReturnInstruction(result, call->id()); | 11811 return ast_context()->ReturnInstruction(result, call->id()); |
11812 } | 11812 } |
11813 | 11813 |
11814 | 11814 |
11815 void HOptimizedGraphBuilder::GenerateMathSqrtRT(CallRuntime* call) { | 11815 void HOptimizedGraphBuilder::GenerateMathSqrtRT(CallRuntime* call) { |
11816 ASSERT(call->arguments()->length() == 1); | 11816 DCHECK(call->arguments()->length() == 1); |
11817 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11817 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11818 HValue* value = Pop(); | 11818 HValue* value = Pop(); |
11819 HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt); | 11819 HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt); |
11820 return ast_context()->ReturnInstruction(result, call->id()); | 11820 return ast_context()->ReturnInstruction(result, call->id()); |
11821 } | 11821 } |
11822 | 11822 |
11823 | 11823 |
11824 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { | 11824 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { |
11825 ASSERT(call->arguments()->length() == 1); | 11825 DCHECK(call->arguments()->length() == 1); |
11826 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 11826 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
11827 HValue* value = Pop(); | 11827 HValue* value = Pop(); |
11828 HGetCachedArrayIndex* result = New<HGetCachedArrayIndex>(value); | 11828 HGetCachedArrayIndex* result = New<HGetCachedArrayIndex>(value); |
11829 return ast_context()->ReturnInstruction(result, call->id()); | 11829 return ast_context()->ReturnInstruction(result, call->id()); |
11830 } | 11830 } |
11831 | 11831 |
11832 | 11832 |
11833 void HOptimizedGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { | 11833 void HOptimizedGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { |
11834 return Bailout(kInlinedRuntimeFunctionFastAsciiArrayJoin); | 11834 return Bailout(kInlinedRuntimeFunctionFastAsciiArrayJoin); |
11835 } | 11835 } |
(...skipping 11 matching lines...) Expand all Loading... |
11847 | 11847 |
11848 | 11848 |
11849 void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode( | 11849 void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode( |
11850 CallRuntime* call) { | 11850 CallRuntime* call) { |
11851 Add<HDebugBreak>(); | 11851 Add<HDebugBreak>(); |
11852 return ast_context()->ReturnValue(graph()->GetConstant0()); | 11852 return ast_context()->ReturnValue(graph()->GetConstant0()); |
11853 } | 11853 } |
11854 | 11854 |
11855 | 11855 |
11856 void HOptimizedGraphBuilder::GenerateDebugIsActive(CallRuntime* call) { | 11856 void HOptimizedGraphBuilder::GenerateDebugIsActive(CallRuntime* call) { |
11857 ASSERT(call->arguments()->length() == 0); | 11857 DCHECK(call->arguments()->length() == 0); |
11858 HValue* ref = | 11858 HValue* ref = |
11859 Add<HConstant>(ExternalReference::debug_is_active_address(isolate())); | 11859 Add<HConstant>(ExternalReference::debug_is_active_address(isolate())); |
11860 HValue* value = Add<HLoadNamedField>( | 11860 HValue* value = Add<HLoadNamedField>( |
11861 ref, static_cast<HValue*>(NULL), HObjectAccess::ForExternalUInteger8()); | 11861 ref, static_cast<HValue*>(NULL), HObjectAccess::ForExternalUInteger8()); |
11862 return ast_context()->ReturnValue(value); | 11862 return ast_context()->ReturnValue(value); |
11863 } | 11863 } |
11864 | 11864 |
11865 | 11865 |
11866 #undef CHECK_BAILOUT | 11866 #undef CHECK_BAILOUT |
11867 #undef CHECK_ALIVE | 11867 #undef CHECK_ALIVE |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11964 if (other->outer_ != NULL) outer_ = other->outer_->Copy(); // Deep copy. | 11964 if (other->outer_ != NULL) outer_ = other->outer_->Copy(); // Deep copy. |
11965 entry_ = other->entry_; | 11965 entry_ = other->entry_; |
11966 pop_count_ = other->pop_count_; | 11966 pop_count_ = other->pop_count_; |
11967 push_count_ = other->push_count_; | 11967 push_count_ = other->push_count_; |
11968 specials_count_ = other->specials_count_; | 11968 specials_count_ = other->specials_count_; |
11969 ast_id_ = other->ast_id_; | 11969 ast_id_ = other->ast_id_; |
11970 } | 11970 } |
11971 | 11971 |
11972 | 11972 |
11973 void HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) { | 11973 void HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) { |
11974 ASSERT(!block->IsLoopHeader()); | 11974 DCHECK(!block->IsLoopHeader()); |
11975 ASSERT(values_.length() == other->values_.length()); | 11975 DCHECK(values_.length() == other->values_.length()); |
11976 | 11976 |
11977 int length = values_.length(); | 11977 int length = values_.length(); |
11978 for (int i = 0; i < length; ++i) { | 11978 for (int i = 0; i < length; ++i) { |
11979 HValue* value = values_[i]; | 11979 HValue* value = values_[i]; |
11980 if (value != NULL && value->IsPhi() && value->block() == block) { | 11980 if (value != NULL && value->IsPhi() && value->block() == block) { |
11981 // There is already a phi for the i'th value. | 11981 // There is already a phi for the i'th value. |
11982 HPhi* phi = HPhi::cast(value); | 11982 HPhi* phi = HPhi::cast(value); |
11983 // Assert index is correct and that we haven't missed an incoming edge. | 11983 // Assert index is correct and that we haven't missed an incoming edge. |
11984 ASSERT(phi->merged_index() == i || !phi->HasMergedIndex()); | 11984 DCHECK(phi->merged_index() == i || !phi->HasMergedIndex()); |
11985 ASSERT(phi->OperandCount() == block->predecessors()->length()); | 11985 DCHECK(phi->OperandCount() == block->predecessors()->length()); |
11986 phi->AddInput(other->values_[i]); | 11986 phi->AddInput(other->values_[i]); |
11987 } else if (values_[i] != other->values_[i]) { | 11987 } else if (values_[i] != other->values_[i]) { |
11988 // There is a fresh value on the incoming edge, a phi is needed. | 11988 // There is a fresh value on the incoming edge, a phi is needed. |
11989 ASSERT(values_[i] != NULL && other->values_[i] != NULL); | 11989 DCHECK(values_[i] != NULL && other->values_[i] != NULL); |
11990 HPhi* phi = block->AddNewPhi(i); | 11990 HPhi* phi = block->AddNewPhi(i); |
11991 HValue* old_value = values_[i]; | 11991 HValue* old_value = values_[i]; |
11992 for (int j = 0; j < block->predecessors()->length(); j++) { | 11992 for (int j = 0; j < block->predecessors()->length(); j++) { |
11993 phi->AddInput(old_value); | 11993 phi->AddInput(old_value); |
11994 } | 11994 } |
11995 phi->AddInput(other->values_[i]); | 11995 phi->AddInput(other->values_[i]); |
11996 this->values_[i] = phi; | 11996 this->values_[i] = phi; |
11997 } | 11997 } |
11998 } | 11998 } |
11999 } | 11999 } |
12000 | 12000 |
12001 | 12001 |
12002 void HEnvironment::Bind(int index, HValue* value) { | 12002 void HEnvironment::Bind(int index, HValue* value) { |
12003 ASSERT(value != NULL); | 12003 DCHECK(value != NULL); |
12004 assigned_variables_.Add(index, zone()); | 12004 assigned_variables_.Add(index, zone()); |
12005 values_[index] = value; | 12005 values_[index] = value; |
12006 } | 12006 } |
12007 | 12007 |
12008 | 12008 |
12009 bool HEnvironment::HasExpressionAt(int index) const { | 12009 bool HEnvironment::HasExpressionAt(int index) const { |
12010 return index >= parameter_count_ + specials_count_ + local_count_; | 12010 return index >= parameter_count_ + specials_count_ + local_count_; |
12011 } | 12011 } |
12012 | 12012 |
12013 | 12013 |
12014 bool HEnvironment::ExpressionStackIsEmpty() const { | 12014 bool HEnvironment::ExpressionStackIsEmpty() const { |
12015 ASSERT(length() >= first_expression_index()); | 12015 DCHECK(length() >= first_expression_index()); |
12016 return length() == first_expression_index(); | 12016 return length() == first_expression_index(); |
12017 } | 12017 } |
12018 | 12018 |
12019 | 12019 |
12020 void HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) { | 12020 void HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) { |
12021 int count = index_from_top + 1; | 12021 int count = index_from_top + 1; |
12022 int index = values_.length() - count; | 12022 int index = values_.length() - count; |
12023 ASSERT(HasExpressionAt(index)); | 12023 DCHECK(HasExpressionAt(index)); |
12024 // The push count must include at least the element in question or else | 12024 // The push count must include at least the element in question or else |
12025 // the new value will not be included in this environment's history. | 12025 // the new value will not be included in this environment's history. |
12026 if (push_count_ < count) { | 12026 if (push_count_ < count) { |
12027 // This is the same effect as popping then re-pushing 'count' elements. | 12027 // This is the same effect as popping then re-pushing 'count' elements. |
12028 pop_count_ += (count - push_count_); | 12028 pop_count_ += (count - push_count_); |
12029 push_count_ = count; | 12029 push_count_ = count; |
12030 } | 12030 } |
12031 values_[index] = value; | 12031 values_[index] = value; |
12032 } | 12032 } |
12033 | 12033 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12077 return new_env; | 12077 return new_env; |
12078 } | 12078 } |
12079 | 12079 |
12080 | 12080 |
12081 HEnvironment* HEnvironment::CopyForInlining( | 12081 HEnvironment* HEnvironment::CopyForInlining( |
12082 Handle<JSFunction> target, | 12082 Handle<JSFunction> target, |
12083 int arguments, | 12083 int arguments, |
12084 FunctionLiteral* function, | 12084 FunctionLiteral* function, |
12085 HConstant* undefined, | 12085 HConstant* undefined, |
12086 InliningKind inlining_kind) const { | 12086 InliningKind inlining_kind) const { |
12087 ASSERT(frame_type() == JS_FUNCTION); | 12087 DCHECK(frame_type() == JS_FUNCTION); |
12088 | 12088 |
12089 // Outer environment is a copy of this one without the arguments. | 12089 // Outer environment is a copy of this one without the arguments. |
12090 int arity = function->scope()->num_parameters(); | 12090 int arity = function->scope()->num_parameters(); |
12091 | 12091 |
12092 HEnvironment* outer = Copy(); | 12092 HEnvironment* outer = Copy(); |
12093 outer->Drop(arguments + 1); // Including receiver. | 12093 outer->Drop(arguments + 1); // Including receiver. |
12094 outer->ClearHistory(); | 12094 outer->ClearHistory(); |
12095 | 12095 |
12096 if (inlining_kind == CONSTRUCT_CALL_RETURN) { | 12096 if (inlining_kind == CONSTRUCT_CALL_RETURN) { |
12097 // Create artificial constructor stub environment. The receiver should | 12097 // Create artificial constructor stub environment. The receiver should |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12165 CodeStub::Major major_key = info->code_stub()->MajorKey(); | 12165 CodeStub::Major major_key = info->code_stub()->MajorKey(); |
12166 PrintStringProperty("name", CodeStub::MajorName(major_key, false)); | 12166 PrintStringProperty("name", CodeStub::MajorName(major_key, false)); |
12167 PrintStringProperty("method", "stub"); | 12167 PrintStringProperty("method", "stub"); |
12168 } | 12168 } |
12169 PrintLongProperty("date", | 12169 PrintLongProperty("date", |
12170 static_cast<int64_t>(base::OS::TimeCurrentMillis())); | 12170 static_cast<int64_t>(base::OS::TimeCurrentMillis())); |
12171 } | 12171 } |
12172 | 12172 |
12173 | 12173 |
12174 void HTracer::TraceLithium(const char* name, LChunk* chunk) { | 12174 void HTracer::TraceLithium(const char* name, LChunk* chunk) { |
12175 ASSERT(!chunk->isolate()->concurrent_recompilation_enabled()); | 12175 DCHECK(!chunk->isolate()->concurrent_recompilation_enabled()); |
12176 AllowHandleDereference allow_deref; | 12176 AllowHandleDereference allow_deref; |
12177 AllowDeferredHandleDereference allow_deferred_deref; | 12177 AllowDeferredHandleDereference allow_deferred_deref; |
12178 Trace(name, chunk->graph(), chunk); | 12178 Trace(name, chunk->graph(), chunk); |
12179 } | 12179 } |
12180 | 12180 |
12181 | 12181 |
12182 void HTracer::TraceHydrogen(const char* name, HGraph* graph) { | 12182 void HTracer::TraceHydrogen(const char* name, HGraph* graph) { |
12183 ASSERT(!graph->isolate()->concurrent_recompilation_enabled()); | 12183 DCHECK(!graph->isolate()->concurrent_recompilation_enabled()); |
12184 AllowHandleDereference allow_deref; | 12184 AllowHandleDereference allow_deref; |
12185 AllowDeferredHandleDereference allow_deferred_deref; | 12185 AllowDeferredHandleDereference allow_deferred_deref; |
12186 Trace(name, graph, NULL); | 12186 Trace(name, graph, NULL); |
12187 } | 12187 } |
12188 | 12188 |
12189 | 12189 |
12190 void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) { | 12190 void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) { |
12191 Tag tag(this, "cfg"); | 12191 Tag tag(this, "cfg"); |
12192 PrintStringProperty("name", name); | 12192 PrintStringProperty("name", name); |
12193 const ZoneList<HBasicBlock*>* blocks = graph->blocks(); | 12193 const ZoneList<HBasicBlock*>* blocks = graph->blocks(); |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12341 if (range != NULL && !range->IsEmpty()) { | 12341 if (range != NULL && !range->IsEmpty()) { |
12342 PrintIndent(); | 12342 PrintIndent(); |
12343 trace_.Add("%d %s", range->id(), type); | 12343 trace_.Add("%d %s", range->id(), type); |
12344 if (range->HasRegisterAssigned()) { | 12344 if (range->HasRegisterAssigned()) { |
12345 LOperand* op = range->CreateAssignedOperand(zone); | 12345 LOperand* op = range->CreateAssignedOperand(zone); |
12346 int assigned_reg = op->index(); | 12346 int assigned_reg = op->index(); |
12347 if (op->IsDoubleRegister()) { | 12347 if (op->IsDoubleRegister()) { |
12348 trace_.Add(" \"%s\"", | 12348 trace_.Add(" \"%s\"", |
12349 DoubleRegister::AllocationIndexToString(assigned_reg)); | 12349 DoubleRegister::AllocationIndexToString(assigned_reg)); |
12350 } else { | 12350 } else { |
12351 ASSERT(op->IsRegister()); | 12351 DCHECK(op->IsRegister()); |
12352 trace_.Add(" \"%s\"", Register::AllocationIndexToString(assigned_reg)); | 12352 trace_.Add(" \"%s\"", Register::AllocationIndexToString(assigned_reg)); |
12353 } | 12353 } |
12354 } else if (range->IsSpilled()) { | 12354 } else if (range->IsSpilled()) { |
12355 LOperand* op = range->TopLevel()->GetSpillOperand(); | 12355 LOperand* op = range->TopLevel()->GetSpillOperand(); |
12356 if (op->IsDoubleStackSlot()) { | 12356 if (op->IsDoubleStackSlot()) { |
12357 trace_.Add(" \"double_stack:%d\"", op->index()); | 12357 trace_.Add(" \"double_stack:%d\"", op->index()); |
12358 } else { | 12358 } else { |
12359 ASSERT(op->IsStackSlot()); | 12359 DCHECK(op->IsStackSlot()); |
12360 trace_.Add(" \"stack:%d\"", op->index()); | 12360 trace_.Add(" \"stack:%d\"", op->index()); |
12361 } | 12361 } |
12362 } | 12362 } |
12363 int parent_index = -1; | 12363 int parent_index = -1; |
12364 if (range->IsChild()) { | 12364 if (range->IsChild()) { |
12365 parent_index = range->parent()->id(); | 12365 parent_index = range->parent()->id(); |
12366 } else { | 12366 } else { |
12367 parent_index = range->id(); | 12367 parent_index = range->id(); |
12368 } | 12368 } |
12369 LOperand* op = range->FirstHint(); | 12369 LOperand* op = range->FirstHint(); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12481 if (ShouldProduceTraceOutput()) { | 12481 if (ShouldProduceTraceOutput()) { |
12482 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 12482 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
12483 } | 12483 } |
12484 | 12484 |
12485 #ifdef DEBUG | 12485 #ifdef DEBUG |
12486 graph_->Verify(false); // No full verify. | 12486 graph_->Verify(false); // No full verify. |
12487 #endif | 12487 #endif |
12488 } | 12488 } |
12489 | 12489 |
12490 } } // namespace v8::internal | 12490 } } // namespace v8::internal |
OLD | NEW |