Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 3776 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3787 } while (false) | 3787 } while (false) |
| 3788 | 3788 |
| 3789 | 3789 |
| 3790 #define CHECK_ALIVE(call) \ | 3790 #define CHECK_ALIVE(call) \ |
| 3791 do { \ | 3791 do { \ |
| 3792 call; \ | 3792 call; \ |
| 3793 if (HasStackOverflow() || current_block() == NULL) return; \ | 3793 if (HasStackOverflow() || current_block() == NULL) return; \ |
| 3794 } while (false) | 3794 } while (false) |
| 3795 | 3795 |
| 3796 | 3796 |
| 3797 #define CHECK_ALIVE_OR_RETURN(call, value) \ | |
| 3798 do { \ | |
| 3799 call; \ | |
| 3800 if (HasStackOverflow() || current_block() == NULL) return value; \ | |
| 3801 } while (false) | |
| 3802 | |
| 3803 | |
| 3797 void HOptimizedGraphBuilder::Bailout(const char* reason) { | 3804 void HOptimizedGraphBuilder::Bailout(const char* reason) { |
| 3798 current_info()->set_bailout_reason(reason); | 3805 current_info()->set_bailout_reason(reason); |
| 3799 SetStackOverflow(); | 3806 SetStackOverflow(); |
| 3800 } | 3807 } |
| 3801 | 3808 |
| 3802 | 3809 |
| 3803 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) { | 3810 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) { |
| 3804 EffectContext for_effect(this); | 3811 EffectContext for_effect(this); |
| 3805 Visit(expr); | 3812 Visit(expr); |
| 3806 } | 3813 } |
| (...skipping 2482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6289 } | 6296 } |
| 6290 | 6297 |
| 6291 | 6298 |
| 6292 HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic( | 6299 HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic( |
| 6293 Property* expr, | 6300 Property* expr, |
| 6294 HValue* object, | 6301 HValue* object, |
| 6295 SmallMapList* types, | 6302 SmallMapList* types, |
| 6296 Handle<String> name) { | 6303 Handle<String> name) { |
| 6297 // Use monomorphic load if property lookup results in the same field index | 6304 // Use monomorphic load if property lookup results in the same field index |
| 6298 // for all maps. Requires special map check on the set of all handled maps. | 6305 // for all maps. Requires special map check on the set of all handled maps. |
| 6306 if (types->length() > kMaxLoadPolymorphism) return NULL; | |
| 6307 | |
| 6299 LookupResult lookup(isolate()); | 6308 LookupResult lookup(isolate()); |
| 6300 int count; | 6309 int count; |
| 6301 Representation representation = Representation::None(); | 6310 Representation representation = Representation::None(); |
| 6302 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. | 6311 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. |
| 6303 for (count = 0; | 6312 for (count = 0; count < types->length(); ++count) { |
| 6304 count < types->length() && count < kMaxLoadPolymorphism; | |
| 6305 ++count) { | |
| 6306 Handle<Map> map = types->at(count); | 6313 Handle<Map> map = types->at(count); |
| 6307 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; | 6314 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; |
| 6308 | 6315 |
| 6309 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); | 6316 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); |
| 6310 Representation new_representation = | 6317 Representation new_representation = |
| 6311 ComputeLoadStoreRepresentation(map, &lookup); | 6318 ComputeLoadStoreRepresentation(map, &lookup); |
| 6312 | 6319 |
| 6313 if (count == 0) { | 6320 if (count == 0) { |
| 6314 // First time through the loop; set access and representation. | 6321 // First time through the loop; set access and representation. |
| 6315 access = new_access; | 6322 access = new_access; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6348 HValue* context = environment()->LookupContext(); | 6355 HValue* context = environment()->LookupContext(); |
| 6349 instr = new(zone()) HLoadNamedFieldPolymorphic( | 6356 instr = new(zone()) HLoadNamedFieldPolymorphic( |
| 6350 context, object, types, name, zone()); | 6357 context, object, types, name, zone()); |
| 6351 } | 6358 } |
| 6352 | 6359 |
| 6353 instr->set_position(expr->position()); | 6360 instr->set_position(expr->position()); |
| 6354 return ast_context()->ReturnInstruction(instr, expr->id()); | 6361 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 6355 } | 6362 } |
| 6356 | 6363 |
| 6357 | 6364 |
| 6365 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( | |
|
Jakob Kummerow
2013/06/14 13:08:05
This method looks very similar to TryLoadPolymorph
| |
| 6366 Assignment* expr, | |
| 6367 HValue* object, | |
| 6368 HValue* value, | |
| 6369 SmallMapList* types, | |
| 6370 Handle<String> name) { | |
| 6371 // Use monomorphic store if property lookup results in the same field index | |
| 6372 // for all maps. Requires special map check on the set of all handled maps. | |
| 6373 if (types->length() > kMaxStorePolymorphism) return false; | |
| 6374 | |
| 6375 LookupResult lookup(isolate()); | |
| 6376 int count; | |
| 6377 Representation representation = Representation::None(); | |
| 6378 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. | |
| 6379 for (count = 0; count < types->length(); ++count) { | |
| 6380 Handle<Map> map = types->at(count); | |
| 6381 // Pass false to ignore transitions. | |
| 6382 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; | |
| 6383 | |
| 6384 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); | |
| 6385 Representation new_representation = | |
| 6386 ComputeLoadStoreRepresentation(map, &lookup); | |
| 6387 | |
| 6388 if (count == 0) { | |
| 6389 // First time through the loop; set access and representation. | |
| 6390 access = new_access; | |
| 6391 representation = new_representation; | |
| 6392 } else if (!representation.IsCompatibleForStore(new_representation)) { | |
| 6393 // Representations did not match. | |
| 6394 break; | |
| 6395 } else if (access.offset() != new_access.offset()) { | |
| 6396 // Offsets did not match. | |
| 6397 break; | |
| 6398 } else if (access.IsInobject() != new_access.IsInobject()) { | |
| 6399 // In-objectness did not match. | |
| 6400 break; | |
| 6401 } | |
| 6402 } | |
| 6403 | |
| 6404 if (count != types->length()) return false; | |
| 6405 | |
| 6406 // Everything matched; can use monomorphic store. | |
| 6407 BuildCheckNonSmi(object); | |
| 6408 AddInstruction(HCheckMaps::New(object, types, zone())); | |
| 6409 HInstruction* store; | |
| 6410 CHECK_ALIVE_OR_RETURN( | |
| 6411 store = BuildStoreNamedField(object, name, value, types->at(0), &lookup), | |
| 6412 true); | |
| 6413 Push(value); | |
| 6414 store->set_position(expr->position()); | |
| 6415 AddInstruction(store); | |
| 6416 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | |
|
Jakob Kummerow
2013/06/14 13:08:05
For the record, I think it's pointless (but safe)
| |
| 6417 ast_context()->ReturnValue(Pop()); | |
| 6418 return true; | |
| 6419 } | |
| 6420 | |
| 6421 | |
| 6358 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( | 6422 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
| 6359 Assignment* expr, | 6423 Assignment* expr, |
| 6360 HValue* object, | 6424 HValue* object, |
| 6361 HValue* value, | 6425 HValue* value, |
| 6362 SmallMapList* types, | 6426 SmallMapList* types, |
| 6363 Handle<String> name) { | 6427 Handle<String> name) { |
| 6428 if (TryStorePolymorphicAsMonomorphic(expr, object, value, types, name)) { | |
| 6429 return; | |
| 6430 } | |
| 6431 | |
| 6364 // TODO(ager): We should recognize when the prototype chains for different | 6432 // TODO(ager): We should recognize when the prototype chains for different |
| 6365 // maps are identical. In that case we can avoid repeatedly generating the | 6433 // maps are identical. In that case we can avoid repeatedly generating the |
| 6366 // same prototype map checks. | 6434 // same prototype map checks. |
| 6367 int count = 0; | 6435 int count = 0; |
| 6368 HBasicBlock* join = NULL; | 6436 HBasicBlock* join = NULL; |
| 6369 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { | 6437 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { |
| 6370 Handle<Map> map = types->at(i); | 6438 Handle<Map> map = types->at(i); |
| 6371 LookupResult lookup(isolate()); | 6439 LookupResult lookup(isolate()); |
| 6372 if (ComputeLoadStoreField(map, name, &lookup, true)) { | 6440 if (ComputeLoadStoreField(map, name, &lookup, true)) { |
| 6373 if (count == 0) { | 6441 if (count == 0) { |
| 6374 BuildCheckNonSmi(object); | 6442 BuildCheckNonSmi(object); |
| 6375 join = graph()->CreateBasicBlock(); | 6443 join = graph()->CreateBasicBlock(); |
| 6376 } | 6444 } |
| 6377 ++count; | 6445 ++count; |
| 6378 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 6446 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
| 6379 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 6447 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| 6380 HCompareMap* compare = | 6448 HCompareMap* compare = |
| 6381 new(zone()) HCompareMap(object, map, if_true, if_false); | 6449 new(zone()) HCompareMap(object, map, if_true, if_false); |
| 6382 current_block()->Finish(compare); | 6450 current_block()->Finish(compare); |
| 6383 | 6451 |
| 6384 set_current_block(if_true); | 6452 set_current_block(if_true); |
| 6385 HInstruction* instr; | 6453 HInstruction* instr; |
| 6386 CHECK_ALIVE(instr = | 6454 CHECK_ALIVE( |
| 6387 BuildStoreNamedField(object, name, value, map, &lookup)); | 6455 instr = BuildStoreNamedField(object, name, value, map, &lookup)); |
| 6388 instr->set_position(expr->position()); | 6456 instr->set_position(expr->position()); |
| 6389 // Goto will add the HSimulate for the store. | 6457 // Goto will add the HSimulate for the store. |
| 6390 AddInstruction(instr); | 6458 AddInstruction(instr); |
| 6391 if (!ast_context()->IsEffect()) Push(value); | 6459 if (!ast_context()->IsEffect()) Push(value); |
| 6392 current_block()->Goto(join); | 6460 current_block()->Goto(join); |
| 6393 | 6461 |
| 6394 set_current_block(if_false); | 6462 set_current_block(if_false); |
| 6395 } | 6463 } |
| 6396 } | 6464 } |
| 6397 | 6465 |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 6421 Drop(1); | 6489 Drop(1); |
| 6422 } | 6490 } |
| 6423 } | 6491 } |
| 6424 return ast_context()->ReturnValue(value); | 6492 return ast_context()->ReturnValue(value); |
| 6425 } | 6493 } |
| 6426 } | 6494 } |
| 6427 | 6495 |
| 6428 ASSERT(join != NULL); | 6496 ASSERT(join != NULL); |
| 6429 join->SetJoinId(expr->id()); | 6497 join->SetJoinId(expr->id()); |
| 6430 set_current_block(join); | 6498 set_current_block(join); |
| 6431 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); | 6499 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
| 6432 } | 6500 } |
| 6433 | 6501 |
| 6434 | 6502 |
| 6435 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 6503 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
| 6436 Property* prop = expr->target()->AsProperty(); | 6504 Property* prop = expr->target()->AsProperty(); |
| 6437 ASSERT(prop != NULL); | 6505 ASSERT(prop != NULL); |
| 6438 CHECK_ALIVE(VisitForValue(prop->obj())); | 6506 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 6439 | 6507 |
| 6440 if (prop->key()->IsPropertyName()) { | 6508 if (prop->key()->IsPropertyName()) { |
| 6441 // Named store. | 6509 // Named store. |
| (...skipping 5129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11571 } | 11639 } |
| 11572 } | 11640 } |
| 11573 | 11641 |
| 11574 #ifdef DEBUG | 11642 #ifdef DEBUG |
| 11575 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 11643 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 11576 if (allocator_ != NULL) allocator_->Verify(); | 11644 if (allocator_ != NULL) allocator_->Verify(); |
| 11577 #endif | 11645 #endif |
| 11578 } | 11646 } |
| 11579 | 11647 |
| 11580 } } // namespace v8::internal | 11648 } } // namespace v8::internal |
| OLD | NEW |