| 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 |