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; |
6316 representation = new_representation; | |
6317 } else if (!representation.IsCompatibleForLoad(new_representation)) { | 6323 } else if (!representation.IsCompatibleForLoad(new_representation)) { |
6318 // Representations did not match. | 6324 // Representations did not match. |
6319 break; | 6325 break; |
6320 } else if (access.offset() != new_access.offset()) { | 6326 } else if (access.offset() != new_access.offset()) { |
6321 // Offsets did not match. | 6327 // Offsets did not match. |
6322 break; | 6328 break; |
6323 } else if (access.IsInobject() != new_access.IsInobject()) { | 6329 } else if (access.IsInobject() != new_access.IsInobject()) { |
6324 // In-objectness did not match. | 6330 // In-objectness did not match. |
6325 break; | 6331 break; |
6326 } | 6332 } |
| 6333 representation = representation.generalize(new_representation); |
6327 } | 6334 } |
6328 | 6335 |
6329 if (count != types->length()) return NULL; | 6336 if (count != types->length()) return NULL; |
6330 | 6337 |
6331 // Everything matched; can use monomorphic load. | 6338 // Everything matched; can use monomorphic load. |
6332 BuildCheckNonSmi(object); | 6339 BuildCheckNonSmi(object); |
6333 AddInstruction(HCheckMaps::New(object, types, zone())); | 6340 AddInstruction(HCheckMaps::New(object, types, zone())); |
6334 return BuildLoadNamedField(object, access, representation); | 6341 return BuildLoadNamedField(object, access, representation); |
6335 } | 6342 } |
6336 | 6343 |
(...skipping 11 matching lines...) Expand all 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( |
| 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 // TODO(verwaest): Merge the checking logic with the code in |
| 6376 // TryLoadPolymorphicAsMonomorphic. |
| 6377 LookupResult lookup(isolate()); |
| 6378 int count; |
| 6379 Representation representation = Representation::None(); |
| 6380 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. |
| 6381 for (count = 0; count < types->length(); ++count) { |
| 6382 Handle<Map> map = types->at(count); |
| 6383 // Pass false to ignore transitions. |
| 6384 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; |
| 6385 |
| 6386 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name); |
| 6387 Representation new_representation = |
| 6388 ComputeLoadStoreRepresentation(map, &lookup); |
| 6389 |
| 6390 if (count == 0) { |
| 6391 // First time through the loop; set access and representation. |
| 6392 access = new_access; |
| 6393 representation = new_representation; |
| 6394 } else if (!representation.IsCompatibleForStore(new_representation)) { |
| 6395 // Representations did not match. |
| 6396 break; |
| 6397 } else if (access.offset() != new_access.offset()) { |
| 6398 // Offsets did not match. |
| 6399 break; |
| 6400 } else if (access.IsInobject() != new_access.IsInobject()) { |
| 6401 // In-objectness did not match. |
| 6402 break; |
| 6403 } |
| 6404 } |
| 6405 |
| 6406 if (count != types->length()) return false; |
| 6407 |
| 6408 // Everything matched; can use monomorphic store. |
| 6409 BuildCheckNonSmi(object); |
| 6410 AddInstruction(HCheckMaps::New(object, types, zone())); |
| 6411 HInstruction* store; |
| 6412 CHECK_ALIVE_OR_RETURN( |
| 6413 store = BuildStoreNamedField(object, name, value, types->at(0), &lookup), |
| 6414 true); |
| 6415 Push(value); |
| 6416 store->set_position(expr->position()); |
| 6417 AddInstruction(store); |
| 6418 AddSimulate(expr->AssignmentId()); |
| 6419 ast_context()->ReturnValue(Pop()); |
| 6420 return true; |
| 6421 } |
| 6422 |
| 6423 |
6358 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( | 6424 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
6359 Assignment* expr, | 6425 Assignment* expr, |
6360 HValue* object, | 6426 HValue* object, |
6361 HValue* value, | 6427 HValue* value, |
6362 SmallMapList* types, | 6428 SmallMapList* types, |
6363 Handle<String> name) { | 6429 Handle<String> name) { |
| 6430 if (TryStorePolymorphicAsMonomorphic(expr, object, value, types, name)) { |
| 6431 return; |
| 6432 } |
| 6433 |
6364 // TODO(ager): We should recognize when the prototype chains for different | 6434 // TODO(ager): We should recognize when the prototype chains for different |
6365 // maps are identical. In that case we can avoid repeatedly generating the | 6435 // maps are identical. In that case we can avoid repeatedly generating the |
6366 // same prototype map checks. | 6436 // same prototype map checks. |
6367 int count = 0; | 6437 int count = 0; |
6368 HBasicBlock* join = NULL; | 6438 HBasicBlock* join = NULL; |
6369 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { | 6439 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { |
6370 Handle<Map> map = types->at(i); | 6440 Handle<Map> map = types->at(i); |
6371 LookupResult lookup(isolate()); | 6441 LookupResult lookup(isolate()); |
6372 if (ComputeLoadStoreField(map, name, &lookup, true)) { | 6442 if (ComputeLoadStoreField(map, name, &lookup, true)) { |
6373 if (count == 0) { | 6443 if (count == 0) { |
6374 BuildCheckNonSmi(object); | 6444 BuildCheckNonSmi(object); |
6375 join = graph()->CreateBasicBlock(); | 6445 join = graph()->CreateBasicBlock(); |
6376 } | 6446 } |
6377 ++count; | 6447 ++count; |
6378 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 6448 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
6379 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 6449 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
6380 HCompareMap* compare = | 6450 HCompareMap* compare = |
6381 new(zone()) HCompareMap(object, map, if_true, if_false); | 6451 new(zone()) HCompareMap(object, map, if_true, if_false); |
6382 current_block()->Finish(compare); | 6452 current_block()->Finish(compare); |
6383 | 6453 |
6384 set_current_block(if_true); | 6454 set_current_block(if_true); |
6385 HInstruction* instr; | 6455 HInstruction* instr; |
6386 CHECK_ALIVE(instr = | 6456 CHECK_ALIVE( |
6387 BuildStoreNamedField(object, name, value, map, &lookup)); | 6457 instr = BuildStoreNamedField(object, name, value, map, &lookup)); |
6388 instr->set_position(expr->position()); | 6458 instr->set_position(expr->position()); |
6389 // Goto will add the HSimulate for the store. | 6459 // Goto will add the HSimulate for the store. |
6390 AddInstruction(instr); | 6460 AddInstruction(instr); |
6391 if (!ast_context()->IsEffect()) Push(value); | 6461 if (!ast_context()->IsEffect()) Push(value); |
6392 current_block()->Goto(join); | 6462 current_block()->Goto(join); |
6393 | 6463 |
6394 set_current_block(if_false); | 6464 set_current_block(if_false); |
6395 } | 6465 } |
6396 } | 6466 } |
6397 | 6467 |
(...skipping 23 matching lines...) Expand all Loading... |
6421 Drop(1); | 6491 Drop(1); |
6422 } | 6492 } |
6423 } | 6493 } |
6424 return ast_context()->ReturnValue(value); | 6494 return ast_context()->ReturnValue(value); |
6425 } | 6495 } |
6426 } | 6496 } |
6427 | 6497 |
6428 ASSERT(join != NULL); | 6498 ASSERT(join != NULL); |
6429 join->SetJoinId(expr->id()); | 6499 join->SetJoinId(expr->id()); |
6430 set_current_block(join); | 6500 set_current_block(join); |
6431 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); | 6501 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
6432 } | 6502 } |
6433 | 6503 |
6434 | 6504 |
6435 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 6505 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
6436 Property* prop = expr->target()->AsProperty(); | 6506 Property* prop = expr->target()->AsProperty(); |
6437 ASSERT(prop != NULL); | 6507 ASSERT(prop != NULL); |
6438 CHECK_ALIVE(VisitForValue(prop->obj())); | 6508 CHECK_ALIVE(VisitForValue(prop->obj())); |
6439 | 6509 |
6440 if (prop->key()->IsPropertyName()) { | 6510 if (prop->key()->IsPropertyName()) { |
6441 // Named store. | 6511 // Named store. |
(...skipping 5129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11571 } | 11641 } |
11572 } | 11642 } |
11573 | 11643 |
11574 #ifdef DEBUG | 11644 #ifdef DEBUG |
11575 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 11645 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
11576 if (allocator_ != NULL) allocator_->Verify(); | 11646 if (allocator_ != NULL) allocator_->Verify(); |
11577 #endif | 11647 #endif |
11578 } | 11648 } |
11579 | 11649 |
11580 } } // namespace v8::internal | 11650 } } // namespace v8::internal |
OLD | NEW |