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

Side by Side Diff: src/hydrogen.cc

Issue 5682010: Deoptimize to the proper target after assignment side effects. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge/build/ia32
Patch Set: Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/full-codegen.h ('k') | src/ia32/full-codegen-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 3281 matching lines...) Expand 10 before | Expand all | Expand 10 after
3292 expr->GetMonomorphicReceiverType()->has_fast_elements(); 3292 expr->GetMonomorphicReceiverType()->has_fast_elements();
3293 3293
3294 instr = is_fast_elements 3294 instr = is_fast_elements
3295 ? BuildStoreKeyedFastElement(object, key, value, expr) 3295 ? BuildStoreKeyedFastElement(object, key, value, expr)
3296 : BuildStoreKeyedGeneric(object, key, value); 3296 : BuildStoreKeyedGeneric(object, key, value);
3297 } 3297 }
3298 3298
3299 Push(value); 3299 Push(value);
3300 instr->set_position(expr->position()); 3300 instr->set_position(expr->position());
3301 AddInstruction(instr); 3301 AddInstruction(instr);
3302 if (instr->HasSideEffects()) AddSimulate(expr->id()); 3302 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3303 ast_context()->ReturnValue(Pop()); 3303 ast_context()->ReturnValue(Pop());
3304 } 3304 }
3305 3305
3306 3306
3307 // Because not every expression has a position and there is not common 3307 // Because not every expression has a position and there is not common
3308 // superclass of Assignment and CountOperation, we cannot just pass the 3308 // superclass of Assignment and CountOperation, we cannot just pass the
3309 // owning expression instead of position and ast_id separately. 3309 // owning expression instead of position and ast_id separately.
3310 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, 3310 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
3311 HValue* value, 3311 HValue* value,
3312 int position, 3312 int position,
(...skipping 24 matching lines...) Expand all
3337 operation->RecordTypeFeedback(oracle()); 3337 operation->RecordTypeFeedback(oracle());
3338 3338
3339 if (var != NULL) { 3339 if (var != NULL) {
3340 if (!var->is_global() && !var->IsStackAllocated()) { 3340 if (!var->is_global() && !var->IsStackAllocated()) {
3341 BAILOUT("non-stack/non-global in compound assignment"); 3341 BAILOUT("non-stack/non-global in compound assignment");
3342 } 3342 }
3343 3343
3344 VISIT_FOR_VALUE(operation); 3344 VISIT_FOR_VALUE(operation);
3345 3345
3346 if (var->is_global()) { 3346 if (var->is_global()) {
3347 HandleGlobalVariableAssignment(var, Top(), expr->position(), expr->id()); 3347 HandleGlobalVariableAssignment(var,
3348 Top(),
3349 expr->position(),
3350 expr->AssignmentId());
3348 } else { 3351 } else {
3349 Bind(var, Top()); 3352 Bind(var, Top());
3350 } 3353 }
3351 ast_context()->ReturnValue(Pop()); 3354 ast_context()->ReturnValue(Pop());
3352 3355
3353 } else if (prop != NULL) { 3356 } else if (prop != NULL) {
3354 prop->RecordTypeFeedback(oracle()); 3357 prop->RecordTypeFeedback(oracle());
3355 3358
3356 if (prop->key()->IsPropertyName()) { 3359 if (prop->key()->IsPropertyName()) {
3357 // Named property. 3360 // Named property.
3358 VISIT_FOR_VALUE(prop->obj()); 3361 VISIT_FOR_VALUE(prop->obj());
3359 HValue* obj = Top(); 3362 HValue* obj = Top();
3360 3363
3361 HInstruction* load = NULL; 3364 HInstruction* load = NULL;
3362 if (prop->IsMonomorphic()) { 3365 if (prop->IsMonomorphic()) {
3363 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 3366 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
3364 Handle<Map> map = prop->GetReceiverTypes()->first(); 3367 Handle<Map> map = prop->GetReceiverTypes()->first();
3365 load = BuildLoadNamed(obj, prop, map, name); 3368 load = BuildLoadNamed(obj, prop, map, name);
3366 } else { 3369 } else {
3367 load = BuildLoadNamedGeneric(obj, prop); 3370 load = BuildLoadNamedGeneric(obj, prop);
3368 } 3371 }
3369 PushAndAdd(load); 3372 PushAndAdd(load);
3370 if (load->HasSideEffects()) AddSimulate(expr->compound_bailout_id()); 3373 if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId());
3371 3374
3372 VISIT_FOR_VALUE(expr->value()); 3375 VISIT_FOR_VALUE(expr->value());
3373 HValue* right = Pop(); 3376 HValue* right = Pop();
3374 HValue* left = Pop(); 3377 HValue* left = Pop();
3375 3378
3376 HInstruction* instr = BuildBinaryOperation(operation, left, right); 3379 HInstruction* instr = BuildBinaryOperation(operation, left, right);
3377 PushAndAdd(instr); 3380 PushAndAdd(instr);
3378 if (instr->HasSideEffects()) AddSimulate(operation->id()); 3381 if (instr->HasSideEffects()) AddSimulate(operation->id());
3379 3382
3380 HInstruction* store = BuildStoreNamed(obj, instr, prop); 3383 HInstruction* store = BuildStoreNamed(obj, instr, prop);
3381 AddInstruction(store); 3384 AddInstruction(store);
3382 if (store->HasSideEffects()) AddSimulate(expr->id());
3383
3384 // Drop the simulated receiver and value. Return the value. 3385 // Drop the simulated receiver and value. Return the value.
3385 Drop(2); 3386 Drop(2);
3386 ast_context()->ReturnValue(instr); 3387 Push(instr);
3388 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
3389 ast_context()->ReturnValue(Pop());
3387 3390
3388 } else { 3391 } else {
3389 // Keyed property. 3392 // Keyed property.
3390 VISIT_FOR_VALUE(prop->obj()); 3393 VISIT_FOR_VALUE(prop->obj());
3391 VISIT_FOR_VALUE(prop->key()); 3394 VISIT_FOR_VALUE(prop->key());
3392 HValue* obj = environment()->ExpressionStackAt(1); 3395 HValue* obj = environment()->ExpressionStackAt(1);
3393 HValue* key = environment()->ExpressionStackAt(0); 3396 HValue* key = environment()->ExpressionStackAt(0);
3394 3397
3395 bool is_fast_elements = prop->IsMonomorphic() && 3398 bool is_fast_elements = prop->IsMonomorphic() &&
3396 prop->GetMonomorphicReceiverType()->has_fast_elements(); 3399 prop->GetMonomorphicReceiverType()->has_fast_elements();
3397 3400
3398 HInstruction* load = is_fast_elements 3401 HInstruction* load = is_fast_elements
3399 ? BuildLoadKeyedFastElement(obj, key, prop) 3402 ? BuildLoadKeyedFastElement(obj, key, prop)
3400 : BuildLoadKeyedGeneric(obj, key); 3403 : BuildLoadKeyedGeneric(obj, key);
3401 PushAndAdd(load); 3404 PushAndAdd(load);
3402 if (load->HasSideEffects()) AddSimulate(expr->compound_bailout_id()); 3405 if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId());
3403 3406
3404 VISIT_FOR_VALUE(expr->value()); 3407 VISIT_FOR_VALUE(expr->value());
3405 HValue* right = Pop(); 3408 HValue* right = Pop();
3406 HValue* left = Pop(); 3409 HValue* left = Pop();
3407 3410
3408 HInstruction* instr = BuildBinaryOperation(operation, left, right); 3411 HInstruction* instr = BuildBinaryOperation(operation, left, right);
3409 PushAndAdd(instr); 3412 PushAndAdd(instr);
3410 if (instr->HasSideEffects()) AddSimulate(operation->id()); 3413 if (instr->HasSideEffects()) AddSimulate(operation->id());
3411 3414
3412 HInstruction* store = is_fast_elements 3415 HInstruction* store = is_fast_elements
3413 ? BuildStoreKeyedFastElement(obj, key, instr, prop) 3416 ? BuildStoreKeyedFastElement(obj, key, instr, prop)
3414 : BuildStoreKeyedGeneric(obj, key, instr); 3417 : BuildStoreKeyedGeneric(obj, key, instr);
3415 AddInstruction(store); 3418 AddInstruction(store);
3416 if (store->HasSideEffects()) AddSimulate(expr->id());
3417
3418 // Drop the simulated receiver, key, and value. Return the value. 3419 // Drop the simulated receiver, key, and value. Return the value.
3419 Drop(3); 3420 Drop(3);
3420 ast_context()->ReturnValue(instr); 3421 Push(instr);
3422 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
3423 ast_context()->ReturnValue(Pop());
3421 } 3424 }
3422 3425
3423 } else { 3426 } else {
3424 BAILOUT("invalid lhs in compound assignment"); 3427 BAILOUT("invalid lhs in compound assignment");
3425 } 3428 }
3426 } 3429 }
3427 3430
3428 3431
3429 void HGraphBuilder::VisitAssignment(Assignment* expr) { 3432 void HGraphBuilder::VisitAssignment(Assignment* expr) {
3430 VariableProxy* proxy = expr->target()->AsVariableProxy(); 3433 VariableProxy* proxy = expr->target()->AsVariableProxy();
3431 Variable* var = proxy->AsVariable(); 3434 Variable* var = proxy->AsVariable();
3432 Property* prop = expr->target()->AsProperty(); 3435 Property* prop = expr->target()->AsProperty();
3433 ASSERT(var == NULL || prop == NULL); 3436 ASSERT(var == NULL || prop == NULL);
3434 3437
3435 if (expr->is_compound()) { 3438 if (expr->is_compound()) {
3436 HandleCompoundAssignment(expr); 3439 HandleCompoundAssignment(expr);
3437 return; 3440 return;
3438 } 3441 }
3439 3442
3440 if (var != NULL) { 3443 if (var != NULL) {
3441 if (proxy->IsArguments()) BAILOUT("assignment to arguments"); 3444 if (proxy->IsArguments()) BAILOUT("assignment to arguments");
3442 3445
3443 // Handle the assignment. 3446 // Handle the assignment.
3444 if (var->is_global()) { 3447 if (var->is_global()) {
3445 VISIT_FOR_VALUE(expr->value()); 3448 VISIT_FOR_VALUE(expr->value());
3446 HandleGlobalVariableAssignment(var, Top(), expr->position(), expr->id()); 3449 HandleGlobalVariableAssignment(var,
3450 Top(),
3451 expr->position(),
3452 expr->AssignmentId());
3447 } else { 3453 } else {
3448 // We allow reference to the arguments object only in assignemtns 3454 // We allow reference to the arguments object only in assignemtns
3449 // to local variables to make sure that the arguments object does 3455 // to local variables to make sure that the arguments object does
3450 // not escape and is not modified. 3456 // not escape and is not modified.
3451 VariableProxy* rhs = expr->value()->AsVariableProxy(); 3457 VariableProxy* rhs = expr->value()->AsVariableProxy();
3452 if (rhs != NULL && 3458 if (rhs != NULL &&
3453 rhs->var()->IsStackAllocated() && 3459 rhs->var()->IsStackAllocated() &&
3454 environment()->Lookup(rhs->var())->CheckFlag(HValue::kIsArguments)) { 3460 environment()->Lookup(rhs->var())->CheckFlag(HValue::kIsArguments)) {
3455 Push(environment()->Lookup(rhs->var())); 3461 Push(environment()->Lookup(rhs->var()));
3456 } else { 3462 } else {
(...skipping 1072 matching lines...) Expand 10 before | Expand all | Expand 10 after
4529 HInstruction* instr = BuildIncrement(value, inc); 4535 HInstruction* instr = BuildIncrement(value, inc);
4530 AddInstruction(instr); 4536 AddInstruction(instr);
4531 4537
4532 if (expr->is_prefix()) { 4538 if (expr->is_prefix()) {
4533 Push(instr); 4539 Push(instr);
4534 } else { 4540 } else {
4535 Push(value); 4541 Push(value);
4536 } 4542 }
4537 4543
4538 if (var->is_global()) { 4544 if (var->is_global()) {
4539 HandleGlobalVariableAssignment(var, instr, expr->position(), expr->id()); 4545 HandleGlobalVariableAssignment(var,
4546 instr,
4547 expr->position(),
4548 expr->AssignmentId());
4540 } else { 4549 } else {
4541 ASSERT(var->IsStackAllocated()); 4550 ASSERT(var->IsStackAllocated());
4542 Bind(var, instr); 4551 Bind(var, instr);
4543 } 4552 }
4544 ast_context()->ReturnValue(Pop()); 4553 ast_context()->ReturnValue(Pop());
4545 4554
4546 } else if (prop != NULL) { 4555 } else if (prop != NULL) {
4547 prop->RecordTypeFeedback(oracle()); 4556 prop->RecordTypeFeedback(oracle());
4548 4557
4549 if (prop->key()->IsPropertyName()) { 4558 if (prop->key()->IsPropertyName()) {
4550 // Named property. 4559 // Named property.
4551 4560
4552 // Match the full code generator stack by simulating an extra stack 4561 // Match the full code generator stack by simulating an extra stack
4553 // element for postfix operations in a value context. 4562 // element for postfix operations in a value context.
4554 if (expr->is_postfix() && !ast_context()->IsEffect()) { 4563 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
4555 Push(graph_->GetConstantUndefined()); 4564 if (has_extra) Push(graph_->GetConstantUndefined());
4556 }
4557 4565
4558 VISIT_FOR_VALUE(prop->obj()); 4566 VISIT_FOR_VALUE(prop->obj());
4559 HValue* obj = Top(); 4567 HValue* obj = Top();
4560 4568
4561 HInstruction* load = NULL; 4569 HInstruction* load = NULL;
4562 if (prop->IsMonomorphic()) { 4570 if (prop->IsMonomorphic()) {
4563 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 4571 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4564 Handle<Map> map = prop->GetReceiverTypes()->first(); 4572 Handle<Map> map = prop->GetReceiverTypes()->first();
4565 load = BuildLoadNamed(obj, prop, map, name); 4573 load = BuildLoadNamed(obj, prop, map, name);
4566 } else { 4574 } else {
4567 load = BuildLoadNamedGeneric(obj, prop); 4575 load = BuildLoadNamedGeneric(obj, prop);
4568 } 4576 }
4569 PushAndAdd(load); 4577 PushAndAdd(load);
4570 if (load->HasSideEffects()) AddSimulate(increment->id()); 4578 if (load->HasSideEffects()) AddSimulate(increment->id());
4571 4579
4572 HValue* value = Pop(); 4580 HValue* before = Pop();
4573
4574 // There is no deoptimization to after the increment, so we don't need 4581 // There is no deoptimization to after the increment, so we don't need
4575 // to simulate the expression stack after this instruction. 4582 // to simulate the expression stack after this instruction.
4576 HInstruction* instr = BuildIncrement(value, inc); 4583 HInstruction* after = BuildIncrement(before, inc);
4577 AddInstruction(instr); 4584 AddInstruction(after);
4578 4585
4579 HInstruction* store = BuildStoreNamed(obj, instr, prop); 4586 HInstruction* store = BuildStoreNamed(obj, after, prop);
4580 AddInstruction(store); 4587 AddInstruction(store);
4581 4588
4582 // Drop simulated receiver and push the result. 4589 // Overwrite the receiver in the bailout environment with the result
4583 Drop(1); 4590 // of the operation, and the placeholder with the original value if
4584 if (expr->is_prefix()) { 4591 // necessary.
4585 Push(instr); 4592 environment()->SetExpressionStackAt(0, after);
4586 } else { 4593 if (has_extra) environment()->SetExpressionStackAt(1, before);
4587 if (!ast_context()->IsEffect()) Drop(1); // Drop simulated zero. 4594 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
4588 Push(value); 4595 Drop(has_extra ? 2 : 1);
4589 }
4590 4596
4591 if (store->HasSideEffects()) AddSimulate(expr->id()); 4597 ast_context()->ReturnValue(expr->is_postfix() ? before : after);
4592 ast_context()->ReturnValue(Pop());
4593 4598
4594 } else { 4599 } else {
4595 // Keyed property. 4600 // Keyed property.
4596 4601
4597 // Match the full code generator stack by simulate an extra stack element 4602 // Match the full code generator stack by simulate an extra stack element
4598 // for postfix operations in a value context. 4603 // for postfix operations in a value context.
4599 if (expr->is_postfix() && !ast_context()->IsEffect()) { 4604 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
4600 Push(graph_->GetConstantUndefined()); 4605 if (has_extra) Push(graph_->GetConstantUndefined());
4601 }
4602 4606
4603 VISIT_FOR_VALUE(prop->obj()); 4607 VISIT_FOR_VALUE(prop->obj());
4604 VISIT_FOR_VALUE(prop->key()); 4608 VISIT_FOR_VALUE(prop->key());
4605
4606 HValue* obj = environment()->ExpressionStackAt(1); 4609 HValue* obj = environment()->ExpressionStackAt(1);
4607 HValue* key = environment()->ExpressionStackAt(0); 4610 HValue* key = environment()->ExpressionStackAt(0);
4608 4611
4609 bool is_fast_elements = prop->IsMonomorphic() && 4612 bool is_fast_elements = prop->IsMonomorphic() &&
4610 prop->GetMonomorphicReceiverType()->has_fast_elements(); 4613 prop->GetMonomorphicReceiverType()->has_fast_elements();
4611 4614
4612 HInstruction* load = is_fast_elements 4615 HInstruction* load = is_fast_elements
4613 ? BuildLoadKeyedFastElement(obj, key, prop) 4616 ? BuildLoadKeyedFastElement(obj, key, prop)
4614 : BuildLoadKeyedGeneric(obj, key); 4617 : BuildLoadKeyedGeneric(obj, key);
4615 PushAndAdd(load); 4618 PushAndAdd(load);
4616 if (load->HasSideEffects()) AddSimulate(increment->id()); 4619 if (load->HasSideEffects()) AddSimulate(increment->id());
4617 4620
4618 HValue* value = Pop(); 4621 HValue* before = Pop();
4619
4620 // There is no deoptimization to after the increment, so we don't need 4622 // There is no deoptimization to after the increment, so we don't need
4621 // to simulate the expression stack after this instruction. 4623 // to simulate the expression stack after this instruction.
4622 HInstruction* instr = BuildIncrement(value, inc); 4624 HInstruction* after = BuildIncrement(before, inc);
4623 AddInstruction(instr); 4625 AddInstruction(after);
4624 4626
4625 HInstruction* store = is_fast_elements 4627 HInstruction* store = is_fast_elements
4626 ? BuildStoreKeyedFastElement(obj, key, instr, prop) 4628 ? BuildStoreKeyedFastElement(obj, key, after, prop)
4627 : new HStoreKeyedGeneric(obj, key, instr); 4629 : new HStoreKeyedGeneric(obj, key, after);
4628 AddInstruction(store); 4630 AddInstruction(store);
4629 4631
4630 // Drop simulated receiver and key and push the result. 4632 // Drop the key from the bailout environment. Overwrite the receiver
4631 Drop(2); 4633 // with the result of the operation, and the placeholder with the
4632 if (expr->is_prefix()) { 4634 // original value if necessary.
4633 Push(instr); 4635 Drop(1);
4634 } else { 4636 environment()->SetExpressionStackAt(0, after);
4635 if (!ast_context()->IsEffect()) Drop(1); // Drop simulated zero. 4637 if (has_extra) environment()->SetExpressionStackAt(1, before);
4636 Push(value); 4638 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
4637 } 4639 Drop(has_extra ? 2 : 1);
4638 4640
4639 if (store->HasSideEffects()) AddSimulate(expr->id()); 4641 ast_context()->ReturnValue(expr->is_postfix() ? before : after);
4640 ast_context()->ReturnValue(Pop());
4641 } 4642 }
4642 4643
4643 } else { 4644 } else {
4644 BAILOUT("invalid lhs in count operation"); 4645 BAILOUT("invalid lhs in count operation");
4645 } 4646 }
4646 } 4647 }
4647 4648
4648 4649
4649 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, 4650 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
4650 HValue* left, 4651 HValue* left,
(...skipping 1014 matching lines...) Expand 10 before | Expand all | Expand 10 after
5665 } 5666 }
5666 5667
5667 #ifdef DEBUG 5668 #ifdef DEBUG
5668 if (graph_ != NULL) graph_->Verify(); 5669 if (graph_ != NULL) graph_->Verify();
5669 if (chunk_ != NULL) chunk_->Verify(); 5670 if (chunk_ != NULL) chunk_->Verify();
5670 if (allocator_ != NULL) allocator_->Verify(); 5671 if (allocator_ != NULL) allocator_->Verify();
5671 #endif 5672 #endif
5672 } 5673 }
5673 5674
5674 } } // namespace v8::internal 5675 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/full-codegen.h ('k') | src/ia32/full-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698