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 |