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

Side by Side Diff: src/hydrogen.cc

Issue 17328005: Merge assignment handling for Assignment and CompoundAssignment (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 6343 matching lines...) Expand 10 before | Expand all | Expand 10 after
6354 instr = new(zone()) HLoadNamedFieldPolymorphic( 6354 instr = new(zone()) HLoadNamedFieldPolymorphic(
6355 context, object, types, name, zone()); 6355 context, object, types, name, zone());
6356 } 6356 }
6357 6357
6358 instr->set_position(expr->position()); 6358 instr->set_position(expr->position());
6359 return ast_context()->ReturnInstruction(instr, expr->id()); 6359 return ast_context()->ReturnInstruction(instr, expr->id());
6360 } 6360 }
6361 6361
6362 6362
6363 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( 6363 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic(
6364 Assignment* expr, 6364 int position,
6365 BailoutId assignment_id,
6365 HValue* object, 6366 HValue* object,
6366 HValue* value, 6367 HValue* value,
6367 SmallMapList* types, 6368 SmallMapList* types,
6368 Handle<String> name) { 6369 Handle<String> name) {
6369 // Use monomorphic store if property lookup results in the same field index 6370 // Use monomorphic store if property lookup results in the same field index
6370 // for all maps. Requires special map check on the set of all handled maps. 6371 // for all maps. Requires special map check on the set of all handled maps.
6371 if (types->length() > kMaxStorePolymorphism) return false; 6372 if (types->length() > kMaxStorePolymorphism) return false;
6372 6373
6373 // TODO(verwaest): Merge the checking logic with the code in 6374 // TODO(verwaest): Merge the checking logic with the code in
6374 // TryLoadPolymorphicAsMonomorphic. 6375 // TryLoadPolymorphicAsMonomorphic.
(...skipping 30 matching lines...) Expand all
6405 6406
6406 // Everything matched; can use monomorphic store. 6407 // Everything matched; can use monomorphic store.
6407 BuildCheckNonSmi(object); 6408 BuildCheckNonSmi(object);
6408 AddInstruction(HCheckMaps::New(object, types, zone())); 6409 AddInstruction(HCheckMaps::New(object, types, zone()));
6409 HInstruction* store; 6410 HInstruction* store;
6410 CHECK_ALIVE_OR_RETURN( 6411 CHECK_ALIVE_OR_RETURN(
6411 store = BuildStoreNamedField( 6412 store = BuildStoreNamedField(
6412 object, name, value, types->at(count - 1), &lookup), 6413 object, name, value, types->at(count - 1), &lookup),
6413 true); 6414 true);
6414 Push(value); 6415 Push(value);
6415 store->set_position(expr->position()); 6416 store->set_position(position);
6416 AddInstruction(store); 6417 AddInstruction(store);
6417 AddSimulate(expr->AssignmentId()); 6418 AddSimulate(assignment_id);
6418 ast_context()->ReturnValue(Pop()); 6419 ast_context()->ReturnValue(Pop());
6419 return true; 6420 return true;
6420 } 6421 }
6421 6422
6422 6423
6423 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( 6424 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField(
6424 Assignment* expr, 6425 BailoutId id,
6426 int position,
6427 BailoutId assignment_id,
6425 HValue* object, 6428 HValue* object,
6426 HValue* value, 6429 HValue* value,
6427 SmallMapList* types, 6430 SmallMapList* types,
6428 Handle<String> name) { 6431 Handle<String> name) {
6429 if (TryStorePolymorphicAsMonomorphic(expr, object, value, types, name)) { 6432 if (TryStorePolymorphicAsMonomorphic(
6433 position, assignment_id, object, value, types, name)) {
6430 return; 6434 return;
6431 } 6435 }
6432 6436
6433 // TODO(ager): We should recognize when the prototype chains for different 6437 // TODO(ager): We should recognize when the prototype chains for different
6434 // maps are identical. In that case we can avoid repeatedly generating the 6438 // maps are identical. In that case we can avoid repeatedly generating the
6435 // same prototype map checks. 6439 // same prototype map checks.
6436 int count = 0; 6440 int count = 0;
6437 HBasicBlock* join = NULL; 6441 HBasicBlock* join = NULL;
6438 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { 6442 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) {
6439 Handle<Map> map = types->at(i); 6443 Handle<Map> map = types->at(i);
6440 LookupResult lookup(isolate()); 6444 LookupResult lookup(isolate());
6441 if (ComputeLoadStoreField(map, name, &lookup, true)) { 6445 if (ComputeLoadStoreField(map, name, &lookup, true)) {
6442 if (count == 0) { 6446 if (count == 0) {
6443 BuildCheckNonSmi(object); 6447 BuildCheckNonSmi(object);
6444 join = graph()->CreateBasicBlock(); 6448 join = graph()->CreateBasicBlock();
6445 } 6449 }
6446 ++count; 6450 ++count;
6447 HBasicBlock* if_true = graph()->CreateBasicBlock(); 6451 HBasicBlock* if_true = graph()->CreateBasicBlock();
6448 HBasicBlock* if_false = graph()->CreateBasicBlock(); 6452 HBasicBlock* if_false = graph()->CreateBasicBlock();
6449 HCompareMap* compare = 6453 HCompareMap* compare =
6450 new(zone()) HCompareMap(object, map, if_true, if_false); 6454 new(zone()) HCompareMap(object, map, if_true, if_false);
6451 current_block()->Finish(compare); 6455 current_block()->Finish(compare);
6452 6456
6453 set_current_block(if_true); 6457 set_current_block(if_true);
6454 HInstruction* instr; 6458 HInstruction* instr;
6455 CHECK_ALIVE( 6459 CHECK_ALIVE(
6456 instr = BuildStoreNamedField(object, name, value, map, &lookup)); 6460 instr = BuildStoreNamedField(object, name, value, map, &lookup));
6457 instr->set_position(expr->position()); 6461 instr->set_position(position);
6458 // Goto will add the HSimulate for the store. 6462 // Goto will add the HSimulate for the store.
6459 AddInstruction(instr); 6463 AddInstruction(instr);
6460 if (!ast_context()->IsEffect()) Push(value); 6464 if (!ast_context()->IsEffect()) Push(value);
6461 current_block()->Goto(join); 6465 current_block()->Goto(join);
6462 6466
6463 set_current_block(if_false); 6467 set_current_block(if_false);
6464 } 6468 }
6465 } 6469 }
6466 6470
6467 // Finish up. Unconditionally deoptimize if we've handled all the maps we 6471 // Finish up. Unconditionally deoptimize if we've handled all the maps we
6468 // know about and do not want to handle ones we've never seen. Otherwise 6472 // know about and do not want to handle ones we've never seen. Otherwise
6469 // use a generic IC. 6473 // use a generic IC.
6470 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { 6474 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
6471 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); 6475 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses);
6472 } else { 6476 } else {
6473 HInstruction* instr = BuildStoreNamedGeneric(object, name, value); 6477 HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
6474 instr->set_position(expr->position()); 6478 instr->set_position(position);
6475 AddInstruction(instr); 6479 AddInstruction(instr);
6476 6480
6477 if (join != NULL) { 6481 if (join != NULL) {
6478 if (!ast_context()->IsEffect()) Push(value); 6482 if (!ast_context()->IsEffect()) Push(value);
6479 current_block()->Goto(join); 6483 current_block()->Goto(join);
6480 } else { 6484 } else {
6481 // The HSimulate for the store should not see the stored value in 6485 // The HSimulate for the store should not see the stored value in
6482 // effect contexts (it is not materialized at expr->id() in the 6486 // effect contexts (it is not materialized at expr->id() in the
6483 // unoptimized code). 6487 // unoptimized code).
6484 if (instr->HasObservableSideEffects()) { 6488 if (instr->HasObservableSideEffects()) {
6485 if (ast_context()->IsEffect()) { 6489 if (ast_context()->IsEffect()) {
6486 AddSimulate(expr->id(), REMOVABLE_SIMULATE); 6490 AddSimulate(id, REMOVABLE_SIMULATE);
6487 } else { 6491 } else {
6488 Push(value); 6492 Push(value);
6489 AddSimulate(expr->id(), REMOVABLE_SIMULATE); 6493 AddSimulate(id, REMOVABLE_SIMULATE);
6490 Drop(1); 6494 Drop(1);
6491 } 6495 }
6492 } 6496 }
6493 return ast_context()->ReturnValue(value); 6497 return ast_context()->ReturnValue(value);
6494 } 6498 }
6495 } 6499 }
6496 6500
6497 ASSERT(join != NULL); 6501 ASSERT(join != NULL);
6498 join->SetJoinId(expr->id()); 6502 join->SetJoinId(id);
6499 set_current_block(join); 6503 set_current_block(join);
6500 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); 6504 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
6501 } 6505 }
6502 6506
6503 6507
6504 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { 6508 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
6505 Property* prop = expr->target()->AsProperty(); 6509 Property* prop = expr->target()->AsProperty();
6506 ASSERT(prop != NULL); 6510 ASSERT(prop != NULL);
6507 CHECK_ALIVE(VisitForValue(prop->obj())); 6511 CHECK_ALIVE(VisitForValue(prop->obj()));
6508 6512
6509 if (prop->key()->IsPropertyName()) { 6513 if (prop->key()->IsPropertyName()) {
6510 // Named store. 6514 // Named store.
6511 CHECK_ALIVE(VisitForValue(expr->value())); 6515 CHECK_ALIVE(VisitForValue(expr->value()));
6512 HValue* value = environment()->ExpressionStackAt(0); 6516 HValue* value = environment()->ExpressionStackAt(0);
6513 HValue* object = environment()->ExpressionStackAt(1); 6517 HValue* object = environment()->ExpressionStackAt(1);
6514 6518
6515 Literal* key = prop->key()->AsLiteral(); 6519 return BuildStoreNamed(expr, expr->id(), expr->position(),
6516 Handle<String> name = Handle<String>::cast(key->handle()); 6520 expr->AssignmentId(), prop, object, value);
6517 ASSERT(!name.is_null());
6518
6519 HInstruction* instr = NULL;
6520 SmallMapList* types = expr->GetReceiverTypes();
6521 bool monomorphic = expr->IsMonomorphic();
6522 Handle<Map> map;
6523 if (monomorphic) {
6524 map = types->first();
6525 if (map->is_dictionary_map()) monomorphic = false;
6526 }
6527 if (monomorphic) {
6528 Handle<JSFunction> setter;
6529 Handle<JSObject> holder;
6530 if (LookupSetter(map, name, &setter, &holder)) {
6531 AddCheckConstantFunction(holder, object, map);
6532 if (FLAG_inline_accessors && TryInlineSetter(setter, expr, value)) {
6533 return;
6534 }
6535 Drop(2);
6536 AddInstruction(new(zone()) HPushArgument(object));
6537 AddInstruction(new(zone()) HPushArgument(value));
6538 instr = new(zone()) HCallConstantFunction(setter, 2);
6539 } else {
6540 Drop(2);
6541 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object,
6542 name,
6543 value,
6544 map));
6545 }
6546
6547 } else if (types != NULL && types->length() > 1) {
6548 Drop(2);
6549 return HandlePolymorphicStoreNamedField(expr, object, value, types, name);
6550 } else {
6551 Drop(2);
6552 instr = BuildStoreNamedGeneric(object, name, value);
6553 }
6554
6555 Push(value);
6556 instr->set_position(expr->position());
6557 AddInstruction(instr);
6558 if (instr->HasObservableSideEffects()) {
6559 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE);
6560 }
6561 return ast_context()->ReturnValue(Pop());
6562
6563 } else { 6521 } else {
6564 // Keyed store. 6522 // Keyed store.
6565 CHECK_ALIVE(VisitForValue(prop->key())); 6523 CHECK_ALIVE(VisitForValue(prop->key()));
6566 CHECK_ALIVE(VisitForValue(expr->value())); 6524 CHECK_ALIVE(VisitForValue(expr->value()));
6567 HValue* value = environment()->ExpressionStackAt(0); 6525 HValue* value = environment()->ExpressionStackAt(0);
6568 HValue* key = environment()->ExpressionStackAt(1); 6526 HValue* key = environment()->ExpressionStackAt(1);
6569 HValue* object = environment()->ExpressionStackAt(2); 6527 HValue* object = environment()->ExpressionStackAt(2);
6570 bool has_side_effects = false; 6528 bool has_side_effects = false;
6571 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), 6529 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(),
6572 expr->position(), 6530 expr->position(),
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
6611 value, 6569 value,
6612 function_strict_mode_flag()); 6570 function_strict_mode_flag());
6613 instr->set_position(position); 6571 instr->set_position(position);
6614 AddInstruction(instr); 6572 AddInstruction(instr);
6615 ASSERT(instr->HasObservableSideEffects()); 6573 ASSERT(instr->HasObservableSideEffects());
6616 AddSimulate(ast_id, REMOVABLE_SIMULATE); 6574 AddSimulate(ast_id, REMOVABLE_SIMULATE);
6617 } 6575 }
6618 } 6576 }
6619 6577
6620 6578
6579 void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr,
6580 BailoutId id,
6581 int position,
6582 BailoutId assignment_id,
6583 Property* prop,
6584 HValue* object,
6585 HValue* value) {
6586 Literal* key = prop->key()->AsLiteral();
6587 Handle<String> name = Handle<String>::cast(key->handle());
6588 ASSERT(!name.is_null());
6589
6590 HInstruction* instr = NULL;
6591 SmallMapList* types = expr->GetReceiverTypes();
6592 bool monomorphic = expr->IsMonomorphic();
6593 Handle<Map> map;
6594 if (monomorphic) {
6595 map = types->first();
6596 if (map->is_dictionary_map()) monomorphic = false;
6597 }
6598 if (monomorphic) {
6599 Handle<JSFunction> setter;
6600 Handle<JSObject> holder;
6601 if (LookupSetter(map, name, &setter, &holder)) {
6602 AddCheckConstantFunction(holder, object, map);
6603 if (FLAG_inline_accessors &&
6604 TryInlineSetter(setter, id, assignment_id, value)) {
6605 return;
6606 }
6607 Drop(2);
6608 AddInstruction(new(zone()) HPushArgument(object));
6609 AddInstruction(new(zone()) HPushArgument(value));
6610 instr = new(zone()) HCallConstantFunction(setter, 2);
6611 } else {
6612 Drop(2);
6613 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object,
6614 name,
6615 value,
6616 map));
6617 }
6618
6619 } else if (types != NULL && types->length() > 1) {
6620 Drop(2);
6621 return HandlePolymorphicStoreNamedField(
6622 id, position, assignment_id, object, value, types, name);
6623 } else {
6624 Drop(2);
6625 instr = BuildStoreNamedGeneric(object, name, value);
6626 }
6627
6628 Push(value);
6629 instr->set_position(position);
6630 AddInstruction(instr);
6631 if (instr->HasObservableSideEffects()) {
6632 AddSimulate(assignment_id, REMOVABLE_SIMULATE);
6633 }
6634 return ast_context()->ReturnValue(Pop());
6635 }
6636
6637
6621 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { 6638 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
6622 Expression* target = expr->target(); 6639 Expression* target = expr->target();
6623 VariableProxy* proxy = target->AsVariableProxy(); 6640 VariableProxy* proxy = target->AsVariableProxy();
6624 Property* prop = target->AsProperty(); 6641 Property* prop = target->AsProperty();
6625 ASSERT(proxy == NULL || prop == NULL); 6642 ASSERT(proxy == NULL || prop == NULL);
6626 6643
6627 // We have a second position recorded in the FullCodeGenerator to have 6644 // We have a second position recorded in the FullCodeGenerator to have
6628 // type feedback for the binary operation. 6645 // type feedback for the binary operation.
6629 BinaryOperation* operation = expr->binary_operation(); 6646 BinaryOperation* operation = expr->binary_operation();
6630 6647
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
6737 CHECK_ALIVE(VisitForValue(expr->value())); 6754 CHECK_ALIVE(VisitForValue(expr->value()));
6738 HValue* right = Pop(); 6755 HValue* right = Pop();
6739 HValue* left = Pop(); 6756 HValue* left = Pop();
6740 6757
6741 HInstruction* instr = BuildBinaryOperation(operation, left, right); 6758 HInstruction* instr = BuildBinaryOperation(operation, left, right);
6742 PushAndAdd(instr); 6759 PushAndAdd(instr);
6743 if (instr->HasObservableSideEffects()) { 6760 if (instr->HasObservableSideEffects()) {
6744 AddSimulate(operation->id(), REMOVABLE_SIMULATE); 6761 AddSimulate(operation->id(), REMOVABLE_SIMULATE);
6745 } 6762 }
6746 6763
6747 HInstruction* store; 6764 return BuildStoreNamed(prop, expr->id(), expr->position(),
6748 if (!monomorphic || map->is_observed()) { 6765 expr->AssignmentId(), prop, object, instr);
6749 // If we don't know the monomorphic type, do a generic store.
6750 CHECK_ALIVE(store = BuildStoreNamedGeneric(object, name, instr));
6751 } else {
6752 Handle<JSFunction> setter;
6753 Handle<JSObject> holder;
6754 if (LookupSetter(map, name, &setter, &holder)) {
6755 store = BuildCallSetter(object, instr, map, setter, holder);
6756 } else {
6757 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(object,
6758 name,
6759 instr,
6760 map));
6761 }
6762 }
6763 AddInstruction(store);
6764 // Drop the simulated receiver and value. Return the value.
6765 Drop(2);
6766 Push(instr);
6767 if (store->HasObservableSideEffects()) {
6768 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE);
6769 }
6770 return ast_context()->ReturnValue(Pop());
6771
6772 } else { 6766 } else {
6773 // Keyed property. 6767 // Keyed property.
6774 CHECK_ALIVE(VisitForValue(prop->obj())); 6768 CHECK_ALIVE(VisitForValue(prop->obj()));
6775 CHECK_ALIVE(VisitForValue(prop->key())); 6769 CHECK_ALIVE(VisitForValue(prop->key()));
6776 HValue* obj = environment()->ExpressionStackAt(1); 6770 HValue* obj = environment()->ExpressionStackAt(1);
6777 HValue* key = environment()->ExpressionStackAt(0); 6771 HValue* key = environment()->ExpressionStackAt(0);
6778 6772
6779 bool has_side_effects = false; 6773 bool has_side_effects = false;
6780 HValue* load = HandleKeyedElementAccess( 6774 HValue* load = HandleKeyedElementAccess(
6781 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, 6775 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition,
(...skipping 1442 matching lines...) Expand 10 before | Expand all | Expand 10 after
8224 getter, 8218 getter,
8225 0, 8219 0,
8226 NULL, 8220 NULL,
8227 prop->id(), 8221 prop->id(),
8228 prop->LoadId(), 8222 prop->LoadId(),
8229 GETTER_CALL_RETURN); 8223 GETTER_CALL_RETURN);
8230 } 8224 }
8231 8225
8232 8226
8233 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, 8227 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter,
8234 Assignment* assignment, 8228 BailoutId id,
8229 BailoutId assignment_id,
8235 HValue* implicit_return_value) { 8230 HValue* implicit_return_value) {
8236 return TryInline(CALL_AS_METHOD, 8231 return TryInline(CALL_AS_METHOD,
8237 setter, 8232 setter,
8238 1, 8233 1,
8239 implicit_return_value, 8234 implicit_return_value,
8240 assignment->id(), 8235 id, assignment_id,
8241 assignment->AssignmentId(),
8242 SETTER_CALL_RETURN); 8236 SETTER_CALL_RETURN);
8243 } 8237 }
8244 8238
8245 8239
8246 bool HOptimizedGraphBuilder::TryInlineApply(Handle<JSFunction> function, 8240 bool HOptimizedGraphBuilder::TryInlineApply(Handle<JSFunction> function,
8247 Call* expr, 8241 Call* expr,
8248 int arguments_count) { 8242 int arguments_count) {
8249 return TryInline(CALL_AS_METHOD, 8243 return TryInline(CALL_AS_METHOD,
8250 function, 8244 function,
8251 arguments_count, 8245 arguments_count,
(...skipping 3401 matching lines...) Expand 10 before | Expand all | Expand 10 after
11653 } 11647 }
11654 } 11648 }
11655 11649
11656 #ifdef DEBUG 11650 #ifdef DEBUG
11657 if (graph_ != NULL) graph_->Verify(false); // No full verify. 11651 if (graph_ != NULL) graph_->Verify(false); // No full verify.
11658 if (allocator_ != NULL) allocator_->Verify(); 11652 if (allocator_ != NULL) allocator_->Verify();
11659 #endif 11653 #endif
11660 } 11654 }
11661 11655
11662 } } // namespace v8::internal 11656 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698