OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 5385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5396 } | 5396 } |
5397 map->LookupDescriptor(*holder_, *name_, &lookup_); | 5397 map->LookupDescriptor(*holder_, *name_, &lookup_); |
5398 if (lookup_.IsFound()) return LoadResult(map); | 5398 if (lookup_.IsFound()) return LoadResult(map); |
5399 } | 5399 } |
5400 lookup_.NotFound(); | 5400 lookup_.NotFound(); |
5401 return true; | 5401 return true; |
5402 } | 5402 } |
5403 | 5403 |
5404 | 5404 |
5405 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadMonomorphic() { | 5405 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadMonomorphic() { |
5406 if (!CanInlinePropertyAccess(*map_)) return IsStringLength(); | 5406 if (!CanInlinePropertyAccess(*map_)) { |
| 5407 return IsStringLength() || IsFloat32x4OrInt32x4PropertyCallback(); |
| 5408 } |
5407 if (IsJSObjectFieldAccessor()) return true; | 5409 if (IsJSObjectFieldAccessor()) return true; |
5408 if (!LookupDescriptor()) return false; | 5410 if (!LookupDescriptor()) return false; |
5409 if (lookup_.IsFound()) return true; | 5411 if (lookup_.IsFound()) return true; |
5410 return LookupInPrototypes(); | 5412 return LookupInPrototypes(); |
5411 } | 5413 } |
5412 | 5414 |
5413 | 5415 |
5414 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadAsMonomorphic( | 5416 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadAsMonomorphic( |
5415 SmallMapList* types) { | 5417 SmallMapList* types) { |
5416 ASSERT(map_.is_identical_to(types->first())); | 5418 ASSERT(map_.is_identical_to(types->first())); |
5417 if (!CanLoadMonomorphic()) return false; | 5419 if (!CanLoadMonomorphic()) return false; |
5418 if (types->length() > kMaxLoadPolymorphism) return false; | 5420 if (types->length() > kMaxLoadPolymorphism) return false; |
5419 | 5421 |
5420 if (IsStringLength()) { | 5422 if (IsStringLength()) { |
5421 for (int i = 1; i < types->length(); ++i) { | 5423 for (int i = 1; i < types->length(); ++i) { |
5422 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false; | 5424 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false; |
5423 } | 5425 } |
5424 return true; | 5426 return true; |
5425 } | 5427 } |
5426 | 5428 |
| 5429 if (IsFloat32x4OrInt32x4PropertyCallback()) { |
| 5430 for (int i = 1; i < types->length(); ++i) { |
| 5431 if (types->at(i)->instance_type() == types->first()->instance_type()) { |
| 5432 return false; |
| 5433 } |
| 5434 } |
| 5435 return true; |
| 5436 } |
| 5437 |
5427 if (IsArrayLength()) { | 5438 if (IsArrayLength()) { |
5428 bool is_fast = IsFastElementsKind(map_->elements_kind()); | 5439 bool is_fast = IsFastElementsKind(map_->elements_kind()); |
5429 for (int i = 1; i < types->length(); ++i) { | 5440 for (int i = 1; i < types->length(); ++i) { |
5430 Handle<Map> test_map = types->at(i); | 5441 Handle<Map> test_map = types->at(i); |
5431 if (test_map->instance_type() != JS_ARRAY_TYPE) return false; | 5442 if (test_map->instance_type() != JS_ARRAY_TYPE) return false; |
5432 if (IsFastElementsKind(test_map->elements_kind()) != is_fast) { | 5443 if (IsFastElementsKind(test_map->elements_kind()) != is_fast) { |
5433 return false; | 5444 return false; |
5434 } | 5445 } |
5435 } | 5446 } |
5436 return true; | 5447 return true; |
5437 } | 5448 } |
5438 | 5449 |
5439 if (IsJSObjectFieldAccessor()) { | 5450 if (IsJSObjectFieldAccessor()) { |
5440 InstanceType instance_type = map_->instance_type(); | 5451 InstanceType instance_type = map_->instance_type(); |
5441 for (int i = 1; i < types->length(); ++i) { | 5452 for (int i = 1; i < types->length(); ++i) { |
5442 if (types->at(i)->instance_type() != instance_type) return false; | 5453 if (types->at(i)->instance_type() != instance_type) return false; |
5443 } | 5454 } |
5444 return true; | 5455 return true; |
5445 } | 5456 } |
5446 | 5457 |
5447 for (int i = 1; i < types->length(); ++i) { | 5458 for (int i = 1; i < types->length(); ++i) { |
5448 PropertyAccessInfo test_info(isolate(), types->at(i), name_); | 5459 PropertyAccessInfo test_info(isolate(), types->at(i), name_); |
5449 if (!test_info.IsCompatibleForLoad(this)) return false; | 5460 if (!test_info.IsCompatibleForLoad(this)) return false; |
5450 } | 5461 } |
5451 | 5462 |
5452 return true; | 5463 return true; |
5453 } | 5464 } |
5454 | 5465 |
5455 | 5466 |
| 5467 static BuiltinFunctionId NameToId(Isolate* isolate, Handle<String> name, |
| 5468 InstanceType type) { |
| 5469 BuiltinFunctionId id; |
| 5470 if (name->Equals(isolate->heap()->signMask())) { |
| 5471 id = type == FLOAT32x4_TYPE ? kFloat32x4SignMask : kInt32x4SignMask; |
| 5472 } else if (name->Equals(isolate->heap()->x())) { |
| 5473 id = type == FLOAT32x4_TYPE ? kFloat32x4X : kInt32x4X; |
| 5474 } else if (name->Equals(isolate->heap()->y())) { |
| 5475 id = type == FLOAT32x4_TYPE ? kFloat32x4Y : kInt32x4Y; |
| 5476 } else if (name->Equals(isolate->heap()->z())) { |
| 5477 id = type == FLOAT32x4_TYPE ? kFloat32x4Z : kInt32x4Z; |
| 5478 } else if (name->Equals(isolate->heap()->w())) { |
| 5479 id = type == FLOAT32x4_TYPE ? kFloat32x4W : kInt32x4W; |
| 5480 } else if (name->Equals(isolate->heap()->flagX())) { |
| 5481 ASSERT(type == INT32x4_TYPE); |
| 5482 id = kInt32x4FlagX; |
| 5483 } else if (name->Equals(isolate->heap()->flagY())) { |
| 5484 ASSERT(type == INT32x4_TYPE); |
| 5485 id = kInt32x4FlagY; |
| 5486 } else if (name->Equals(isolate->heap()->flagZ())) { |
| 5487 ASSERT(type == INT32x4_TYPE); |
| 5488 id = kInt32x4FlagZ; |
| 5489 } else if (name->Equals(isolate->heap()->flagW())) { |
| 5490 ASSERT(type == INT32x4_TYPE); |
| 5491 id = kInt32x4FlagW; |
| 5492 } else { |
| 5493 UNREACHABLE(); |
| 5494 id = kFloat32x4OrInt32x4Unreachable; |
| 5495 } |
| 5496 |
| 5497 return id; |
| 5498 } |
| 5499 |
| 5500 |
| 5501 static bool IsSIMDProperty(Handle<String> name, uint8_t* mask) { |
| 5502 SmartArrayPointer<char> cstring = name->ToCString(); |
| 5503 int i = 0; |
| 5504 while (i <= 3) { |
| 5505 int shift = 0; |
| 5506 switch (cstring[i]) { |
| 5507 case 'W': |
| 5508 shift++; |
| 5509 case 'Z': |
| 5510 shift++; |
| 5511 case 'Y': |
| 5512 shift++; |
| 5513 case 'X': |
| 5514 break; |
| 5515 default: |
| 5516 return false; |
| 5517 } |
| 5518 *mask |= (shift << 2*i); |
| 5519 i++; |
| 5520 } |
| 5521 |
| 5522 return true; |
| 5523 } |
| 5524 |
| 5525 |
5456 HInstruction* HOptimizedGraphBuilder::BuildLoadMonomorphic( | 5526 HInstruction* HOptimizedGraphBuilder::BuildLoadMonomorphic( |
5457 PropertyAccessInfo* info, | 5527 PropertyAccessInfo* info, |
5458 HValue* object, | 5528 HValue* object, |
5459 HInstruction* checked_object, | 5529 HInstruction* checked_object, |
5460 BailoutId ast_id, | 5530 BailoutId ast_id, |
5461 BailoutId return_id, | 5531 BailoutId return_id, |
5462 bool can_inline_accessor) { | 5532 bool can_inline_accessor) { |
5463 | 5533 |
5464 HObjectAccess access = HObjectAccess::ForMap(); // bogus default | 5534 HObjectAccess access = HObjectAccess::ForMap(); // bogus default |
5465 if (info->GetJSObjectFieldAccess(&access)) { | 5535 if (info->GetJSObjectFieldAccess(&access)) { |
5466 return New<HLoadNamedField>(checked_object, access); | 5536 return New<HLoadNamedField>(checked_object, access); |
5467 } | 5537 } |
5468 | 5538 |
5469 HValue* checked_holder = checked_object; | 5539 HValue* checked_holder = checked_object; |
5470 if (info->has_holder()) { | 5540 if (info->has_holder()) { |
5471 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype())); | 5541 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype())); |
5472 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); | 5542 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); |
5473 } | 5543 } |
5474 | 5544 |
5475 if (!info->lookup()->IsFound()) return graph()->GetConstantUndefined(); | 5545 if (!info->lookup()->IsFound()) return graph()->GetConstantUndefined(); |
5476 | 5546 |
5477 if (info->lookup()->IsField()) { | 5547 if (info->lookup()->IsField()) { |
| 5548 if (info->map()->constructor()->IsJSFunction()) { |
| 5549 JSFunction* constructor = JSFunction::cast(info->map()->constructor()); |
| 5550 String* class_name = |
| 5551 String::cast(constructor->shared()->instance_class_name()); |
| 5552 uint8_t mask = 0; |
| 5553 if (class_name->Equals(isolate()->heap()->simd()) && |
| 5554 IsSIMDProperty(info->name(), &mask) && |
| 5555 CpuFeatures::IsSupported(SSE2)) { |
| 5556 return New<HConstant>(mask); |
| 5557 } |
| 5558 } |
| 5559 |
5478 return BuildLoadNamedField(checked_holder, info->access()); | 5560 return BuildLoadNamedField(checked_holder, info->access()); |
5479 } | 5561 } |
5480 | 5562 |
5481 if (info->lookup()->IsPropertyCallbacks()) { | 5563 if (info->lookup()->IsPropertyCallbacks()) { |
5482 Push(checked_object); | 5564 Push(checked_object); |
5483 if (FLAG_inline_accessors && | 5565 if (FLAG_inline_accessors && |
5484 can_inline_accessor && | 5566 can_inline_accessor && |
5485 TryInlineGetter(info->accessor(), ast_id, return_id)) { | 5567 TryInlineGetter(info->accessor(), ast_id, return_id)) { |
5486 return NULL; | 5568 return NULL; |
5487 } | 5569 } |
(...skipping 1087 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6575 | 6657 |
6576 | 6658 |
6577 static bool AreStringTypes(SmallMapList* types) { | 6659 static bool AreStringTypes(SmallMapList* types) { |
6578 for (int i = 0; i < types->length(); i++) { | 6660 for (int i = 0; i < types->length(); i++) { |
6579 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false; | 6661 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false; |
6580 } | 6662 } |
6581 return true; | 6663 return true; |
6582 } | 6664 } |
6583 | 6665 |
6584 | 6666 |
| 6667 static bool AreInt32x4Types(SmallMapList* types) { |
| 6668 if (types == NULL || types->length() == 0) return false; |
| 6669 for (int i = 0; i < types->length(); i++) { |
| 6670 if (types->at(i)->instance_type() != INT32x4_TYPE) return false; |
| 6671 } |
| 6672 return true; |
| 6673 } |
| 6674 |
| 6675 |
| 6676 static bool AreFloat32x4Types(SmallMapList* types) { |
| 6677 if (types == NULL || types->length() == 0) return false; |
| 6678 for (int i = 0; i < types->length(); i++) { |
| 6679 if (types->at(i)->instance_type() != FLOAT32x4_TYPE) return false; |
| 6680 } |
| 6681 return true; |
| 6682 } |
| 6683 |
| 6684 |
6585 void HOptimizedGraphBuilder::BuildLoad(Property* expr, | 6685 void HOptimizedGraphBuilder::BuildLoad(Property* expr, |
6586 BailoutId ast_id) { | 6686 BailoutId ast_id) { |
6587 HInstruction* instr = NULL; | 6687 HInstruction* instr = NULL; |
6588 if (expr->IsStringAccess()) { | 6688 if (expr->IsStringAccess()) { |
6589 HValue* index = Pop(); | 6689 HValue* index = Pop(); |
6590 HValue* string = Pop(); | 6690 HValue* string = Pop(); |
6591 HInstruction* char_code = BuildStringCharCodeAt(string, index); | 6691 HInstruction* char_code = BuildStringCharCodeAt(string, index); |
6592 AddInstruction(char_code); | 6692 AddInstruction(char_code); |
6593 instr = NewUncasted<HStringCharFromCode>(char_code); | 6693 instr = NewUncasted<HStringCharFromCode>(char_code); |
6594 | 6694 |
(...skipping 10 matching lines...) Expand all Loading... |
6605 ComputeReceiverTypes(expr, object, &types); | 6705 ComputeReceiverTypes(expr, object, &types); |
6606 ASSERT(types != NULL); | 6706 ASSERT(types != NULL); |
6607 | 6707 |
6608 if (types->length() > 0) { | 6708 if (types->length() > 0) { |
6609 PropertyAccessInfo info(isolate(), types->first(), name); | 6709 PropertyAccessInfo info(isolate(), types->first(), name); |
6610 if (!info.CanLoadAsMonomorphic(types)) { | 6710 if (!info.CanLoadAsMonomorphic(types)) { |
6611 return HandlePolymorphicLoadNamedField( | 6711 return HandlePolymorphicLoadNamedField( |
6612 ast_id, expr->LoadId(), object, types, name); | 6712 ast_id, expr->LoadId(), object, types, name); |
6613 } | 6713 } |
6614 | 6714 |
6615 BuildCheckHeapObject(object); | |
6616 HInstruction* checked_object; | |
6617 if (AreStringTypes(types)) { | 6715 if (AreStringTypes(types)) { |
6618 checked_object = | 6716 BuildCheckHeapObject(object); |
| 6717 HInstruction* checked_object = |
6619 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); | 6718 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); |
| 6719 instr = BuildLoadMonomorphic( |
| 6720 &info, object, checked_object, ast_id, expr->LoadId()); |
| 6721 } else if (AreFloat32x4Types(types) && CpuFeatures::IsSupported(SSE2)) { |
| 6722 Handle<JSFunction> function( |
| 6723 isolate()->native_context()->float32x4_function()); |
| 6724 HInstruction* constant_function = Add<HConstant>(function); |
| 6725 HObjectAccess map_access = HObjectAccess::ForPrototypeOrInitialMap(); |
| 6726 HInstruction* map = Add<HLoadNamedField>(constant_function, map_access); |
| 6727 HObjectAccess prototype_access = HObjectAccess::ForMapPrototype(); |
| 6728 HInstruction* prototype = Add<HLoadNamedField>(map, prototype_access); |
| 6729 Handle<Map> initial_function_prototype_map( |
| 6730 isolate()->native_context()->float32x4_function_prototype_map()); |
| 6731 BuildCheckMap(prototype, initial_function_prototype_map); |
| 6732 BuiltinFunctionId id = NameToId(isolate(), name, FLOAT32x4_TYPE); |
| 6733 instr = NewUncasted<HUnarySIMDOperation>(object, id); |
| 6734 } else if (AreInt32x4Types(types) && CpuFeatures::IsSupported(SSE2)) { |
| 6735 Handle<JSFunction> function( |
| 6736 isolate()->native_context()->int32x4_function()); |
| 6737 HInstruction* constant_function = Add<HConstant>(function); |
| 6738 HObjectAccess map_access = HObjectAccess::ForPrototypeOrInitialMap(); |
| 6739 HInstruction* map = Add<HLoadNamedField>(constant_function, map_access); |
| 6740 HObjectAccess prototype_access = HObjectAccess::ForMapPrototype(); |
| 6741 HInstruction* prototype = Add<HLoadNamedField>(map, prototype_access); |
| 6742 Handle<Map> initial_function_prototype_map( |
| 6743 isolate()->native_context()->int32x4_function_prototype_map()); |
| 6744 BuildCheckMap(prototype, initial_function_prototype_map); |
| 6745 BuiltinFunctionId id = NameToId(isolate(), name, INT32x4_TYPE); |
| 6746 instr = NewUncasted<HUnarySIMDOperation>(object, id); |
6620 } else { | 6747 } else { |
6621 checked_object = Add<HCheckMaps>(object, types); | 6748 BuildCheckHeapObject(object); |
| 6749 HInstruction* checked_object = Add<HCheckMaps>(object, types); |
| 6750 instr = BuildLoadMonomorphic( |
| 6751 &info, object, checked_object, ast_id, expr->LoadId()); |
6622 } | 6752 } |
6623 instr = BuildLoadMonomorphic( | |
6624 &info, object, checked_object, ast_id, expr->LoadId()); | |
6625 if (instr == NULL) return; | 6753 if (instr == NULL) return; |
6626 if (instr->IsLinked()) return ast_context()->ReturnValue(instr); | 6754 if (instr->IsLinked()) return ast_context()->ReturnValue(instr); |
6627 } else { | 6755 } else { |
6628 instr = BuildLoadNamedGeneric(object, name, expr); | 6756 instr = BuildLoadNamedGeneric(object, name, expr); |
6629 } | 6757 } |
6630 | 6758 |
6631 } else { | 6759 } else { |
6632 HValue* key = Pop(); | 6760 HValue* key = Pop(); |
6633 HValue* obj = Pop(); | 6761 HValue* obj = Pop(); |
6634 | 6762 |
(...skipping 741 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7376 if (expr->arguments()->length() == 2) { | 7504 if (expr->arguments()->length() == 2) { |
7377 HValue* right = Pop(); | 7505 HValue* right = Pop(); |
7378 HValue* left = Pop(); | 7506 HValue* left = Pop(); |
7379 Drop(1); // Receiver. | 7507 Drop(1); // Receiver. |
7380 HInstruction* op = HMul::NewImul(zone(), context(), left, right); | 7508 HInstruction* op = HMul::NewImul(zone(), context(), left, right); |
7381 if (drop_extra) Drop(1); // Optionally drop the function. | 7509 if (drop_extra) Drop(1); // Optionally drop the function. |
7382 ast_context()->ReturnInstruction(op, expr->id()); | 7510 ast_context()->ReturnInstruction(op, expr->id()); |
7383 return true; | 7511 return true; |
7384 } | 7512 } |
7385 break; | 7513 break; |
| 7514 case kFloat32x4Zero: |
| 7515 if (expr->arguments()->length() == 0) { |
| 7516 if (!CpuFeatures::IsSupported(SSE2)) return false; |
| 7517 Drop(1); // Receiver. |
| 7518 HInstruction* op = NewUncasted<HNullarySIMDOperation>(id); |
| 7519 if (drop_extra) Drop(1); // Optionally drop the function. |
| 7520 ast_context()->ReturnInstruction(op, expr->id()); |
| 7521 return true; |
| 7522 } |
| 7523 break; |
| 7524 case kSIMDAbs: |
| 7525 case kSIMDNeg: |
| 7526 case kSIMDNegU32: |
| 7527 case kSIMDReciprocal: |
| 7528 case kSIMDReciprocalSqrt: |
| 7529 case kSIMDSqrt: |
| 7530 case kSIMDBitsToFloat32x4: |
| 7531 case kSIMDToFloat32x4: |
| 7532 case kSIMDBitsToInt32x4: |
| 7533 case kSIMDToInt32x4: |
| 7534 case kFloat32x4Splat: |
| 7535 case kInt32x4Splat: |
| 7536 if (expr->arguments()->length() == 1) { |
| 7537 if (!CpuFeatures::IsSupported(SSE2)) return false; |
| 7538 HValue* argument = Pop(); |
| 7539 Drop(1); // Receiver. |
| 7540 HInstruction* op = NewUncasted<HUnarySIMDOperation>(argument, id); |
| 7541 if (drop_extra) Drop(1); // Optionally drop the function. |
| 7542 ast_context()->ReturnInstruction(op, expr->id()); |
| 7543 return true; |
| 7544 } |
| 7545 break; |
| 7546 case kSIMDAdd: |
| 7547 case kSIMDSub: |
| 7548 case kSIMDMul: |
| 7549 case kSIMDDiv: |
| 7550 case kSIMDMin: |
| 7551 case kSIMDMax: |
| 7552 case kSIMDScale: |
| 7553 case kSIMDAnd: |
| 7554 case kSIMDOr: |
| 7555 case kSIMDXor: |
| 7556 case kSIMDAddU32: |
| 7557 case kSIMDSubU32: |
| 7558 case kSIMDMulU32: |
| 7559 case kSIMDShuffle: |
| 7560 case kSIMDShuffleU32: |
| 7561 case kSIMDLessThan: |
| 7562 case kSIMDLessThanOrEqual: |
| 7563 case kSIMDEqual: |
| 7564 case kSIMDNotEqual: |
| 7565 case kSIMDGreaterThanOrEqual: |
| 7566 case kSIMDGreaterThan: |
| 7567 case kSIMDWithX: |
| 7568 case kSIMDWithY: |
| 7569 case kSIMDWithZ: |
| 7570 case kSIMDWithW: |
| 7571 case kSIMDWithXu32: |
| 7572 case kSIMDWithYu32: |
| 7573 case kSIMDWithZu32: |
| 7574 case kSIMDWithWu32: |
| 7575 case kSIMDWithFlagX: |
| 7576 case kSIMDWithFlagY: |
| 7577 case kSIMDWithFlagZ: |
| 7578 case kSIMDWithFlagW: |
| 7579 if (expr->arguments()->length() == 2) { |
| 7580 if (!CpuFeatures::IsSupported(SSE2)) return false; |
| 7581 HValue* right = Pop(); |
| 7582 HValue* left = Pop(); |
| 7583 Drop(1); // Receiver. |
| 7584 HInstruction* op = NewUncasted<HBinarySIMDOperation>(left, right, id); |
| 7585 if (drop_extra) Drop(1); // Optionally drop the function. |
| 7586 ast_context()->ReturnInstruction(op, expr->id()); |
| 7587 return true; |
| 7588 } |
| 7589 break; |
| 7590 case kSIMDSelect: |
| 7591 case kSIMDShuffleMix: |
| 7592 case kSIMDClamp: |
| 7593 if (expr->arguments()->length() == 3) { |
| 7594 if (!CpuFeatures::IsSupported(SSE2)) return false; |
| 7595 HValue* right = Pop(); |
| 7596 HValue* left = Pop(); |
| 7597 HValue* value = Pop(); |
| 7598 Drop(1); // Receiver. |
| 7599 HInstruction* op = |
| 7600 NewUncasted<HTernarySIMDOperation>(value, left, right, id); |
| 7601 if (drop_extra) Drop(1); // Optionally drop the function. |
| 7602 ast_context()->ReturnInstruction(op, expr->id()); |
| 7603 return true; |
| 7604 } |
| 7605 break; |
| 7606 case kFloat32x4Constructor: |
| 7607 case kInt32x4Constructor: |
| 7608 case kInt32x4Bool: |
| 7609 if (expr->arguments()->length() == 4) { |
| 7610 if (!CpuFeatures::IsSupported(SSE2)) return false; |
| 7611 HValue* w = Pop(); |
| 7612 HValue* z = Pop(); |
| 7613 HValue* y = Pop(); |
| 7614 HValue* x = Pop(); |
| 7615 Drop(1); // Receiver. |
| 7616 HInstruction* op = |
| 7617 NewUncasted<HQuarternarySIMDOperation>(x, y, z, w, id); |
| 7618 if (drop_extra) Drop(1); // Optionally drop the function. |
| 7619 ast_context()->ReturnInstruction(op, expr->id()); |
| 7620 return true; |
| 7621 } |
| 7622 break; |
7386 default: | 7623 default: |
7387 // Not supported for inlining yet. | 7624 // Not supported for inlining yet. |
7388 break; | 7625 break; |
7389 } | 7626 } |
7390 return false; | 7627 return false; |
7391 } | 7628 } |
7392 | 7629 |
7393 | 7630 |
7394 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( | 7631 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( |
7395 Call* expr, | 7632 Call* expr, |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7500 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { | 7737 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { |
7501 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | 7738 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
7502 HValue* right = Pop(); | 7739 HValue* right = Pop(); |
7503 HValue* left = Pop(); | 7740 HValue* left = Pop(); |
7504 Drop(1); // Receiver. | 7741 Drop(1); // Receiver. |
7505 HInstruction* result = HMul::NewImul(zone(), context(), left, right); | 7742 HInstruction* result = HMul::NewImul(zone(), context(), left, right); |
7506 ast_context()->ReturnInstruction(result, expr->id()); | 7743 ast_context()->ReturnInstruction(result, expr->id()); |
7507 return true; | 7744 return true; |
7508 } | 7745 } |
7509 break; | 7746 break; |
| 7747 case kFloat32x4Zero: |
| 7748 if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) { |
| 7749 if (!CpuFeatures::IsSupported(SSE2)) return false; |
| 7750 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
| 7751 Drop(1); // Receiver. |
| 7752 HInstruction* op = NewUncasted<HNullarySIMDOperation>(id); |
| 7753 ast_context()->ReturnInstruction(op, expr->id()); |
| 7754 return true; |
| 7755 } |
| 7756 break; |
| 7757 case kSIMDAbs: |
| 7758 case kSIMDNeg: |
| 7759 case kSIMDNegU32: |
| 7760 case kSIMDReciprocal: |
| 7761 case kSIMDReciprocalSqrt: |
| 7762 case kSIMDSqrt: |
| 7763 case kSIMDBitsToFloat32x4: |
| 7764 case kSIMDToFloat32x4: |
| 7765 case kSIMDBitsToInt32x4: |
| 7766 case kSIMDToInt32x4: |
| 7767 case kFloat32x4Splat: |
| 7768 case kInt32x4Splat: |
| 7769 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { |
| 7770 if (!CpuFeatures::IsSupported(SSE2)) return false; |
| 7771 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
| 7772 HValue* argument = Pop(); |
| 7773 Drop(1); // Receiver. |
| 7774 HInstruction* op = NewUncasted<HUnarySIMDOperation>(argument, id); |
| 7775 ast_context()->ReturnInstruction(op, expr->id()); |
| 7776 return true; |
| 7777 } |
| 7778 break; |
| 7779 case kSIMDAdd: |
| 7780 case kSIMDSub: |
| 7781 case kSIMDMul: |
| 7782 case kSIMDDiv: |
| 7783 case kSIMDMin: |
| 7784 case kSIMDMax: |
| 7785 case kSIMDScale: |
| 7786 case kSIMDAnd: |
| 7787 case kSIMDOr: |
| 7788 case kSIMDXor: |
| 7789 case kSIMDAddU32: |
| 7790 case kSIMDSubU32: |
| 7791 case kSIMDMulU32: |
| 7792 case kSIMDShuffle: |
| 7793 case kSIMDShuffleU32: |
| 7794 case kSIMDLessThan: |
| 7795 case kSIMDLessThanOrEqual: |
| 7796 case kSIMDEqual: |
| 7797 case kSIMDNotEqual: |
| 7798 case kSIMDGreaterThanOrEqual: |
| 7799 case kSIMDGreaterThan: |
| 7800 case kSIMDWithX: |
| 7801 case kSIMDWithY: |
| 7802 case kSIMDWithZ: |
| 7803 case kSIMDWithW: |
| 7804 case kSIMDWithXu32: |
| 7805 case kSIMDWithYu32: |
| 7806 case kSIMDWithZu32: |
| 7807 case kSIMDWithWu32: |
| 7808 case kSIMDWithFlagX: |
| 7809 case kSIMDWithFlagY: |
| 7810 case kSIMDWithFlagZ: |
| 7811 case kSIMDWithFlagW: |
| 7812 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { |
| 7813 if (!CpuFeatures::IsSupported(SSE2)) return false; |
| 7814 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
| 7815 HValue* right = Pop(); |
| 7816 HValue* left = Pop(); |
| 7817 Drop(1); // Receiver. |
| 7818 HInstruction* op = NewUncasted<HBinarySIMDOperation>(left, right, id); |
| 7819 ast_context()->ReturnInstruction(op, expr->id()); |
| 7820 return true; |
| 7821 } |
| 7822 break; |
| 7823 case kSIMDSelect: |
| 7824 case kSIMDShuffleMix: |
| 7825 case kSIMDClamp: |
| 7826 if (argument_count == 4 && check_type == RECEIVER_MAP_CHECK) { |
| 7827 if (!CpuFeatures::IsSupported(SSE2)) return false; |
| 7828 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
| 7829 HValue* right = Pop(); |
| 7830 HValue* left = Pop(); |
| 7831 HValue* value = Pop(); |
| 7832 Drop(1); // Receiver. |
| 7833 HInstruction* op = |
| 7834 NewUncasted<HTernarySIMDOperation>(value, left, right, id); |
| 7835 ast_context()->ReturnInstruction(op, expr->id()); |
| 7836 return true; |
| 7837 } |
| 7838 break; |
| 7839 case kInt32x4Bool: |
| 7840 if (argument_count == 5 && check_type == RECEIVER_MAP_CHECK) { |
| 7841 if (!CpuFeatures::IsSupported(SSE2)) return false; |
| 7842 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
| 7843 HValue* w = Pop(); |
| 7844 HValue* z = Pop(); |
| 7845 HValue* y = Pop(); |
| 7846 HValue* x = Pop(); |
| 7847 Drop(1); // Receiver. |
| 7848 HValue* context = environment()->context(); |
| 7849 HInstruction* op = |
| 7850 HQuarternarySIMDOperation::New(zone(), context, x, y, z, w, id); |
| 7851 op->set_position(expr->position()); |
| 7852 ast_context()->ReturnInstruction(op, expr->id()); |
| 7853 return true; |
| 7854 } |
| 7855 break; |
| 7856 case kFloat32x4ArrayGetAt: |
| 7857 case kInt32x4ArrayGetAt: |
| 7858 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { |
| 7859 if (!CpuFeatures::IsSupported(SSE2)) return false; |
| 7860 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
| 7861 HValue* key = Pop(); |
| 7862 HValue* typed32x4_array = Pop(); |
| 7863 ASSERT(typed32x4_array == receiver); |
| 7864 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( |
| 7865 typed32x4_array, key, NULL, |
| 7866 receiver_map->instance_type() == JS_ARRAY_TYPE, |
| 7867 receiver_map->elements_kind(), |
| 7868 false, // is_store. |
| 7869 NEVER_RETURN_HOLE, // load_mode. |
| 7870 STANDARD_STORE); |
| 7871 ast_context()->ReturnValue(instr); |
| 7872 return true; |
| 7873 } |
| 7874 break; |
| 7875 case kFloat32x4ArraySetAt: |
| 7876 case kInt32x4ArraySetAt: |
| 7877 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { |
| 7878 if (!CpuFeatures::IsSupported(SSE2)) return false; |
| 7879 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
| 7880 HValue* value = Pop(); |
| 7881 HValue* key = Pop(); |
| 7882 HValue* typed32x4_array = Pop(); |
| 7883 ASSERT(typed32x4_array == receiver); |
| 7884 // TODO(haitao): add STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS. |
| 7885 KeyedAccessStoreMode store_mode = STANDARD_STORE; |
| 7886 BuildUncheckedMonomorphicElementAccess( |
| 7887 typed32x4_array, key, value, |
| 7888 receiver_map->instance_type() == JS_ARRAY_TYPE, |
| 7889 receiver_map->elements_kind(), |
| 7890 true, // is_store. |
| 7891 NEVER_RETURN_HOLE, // load_mode. |
| 7892 store_mode); |
| 7893 Push(value); |
| 7894 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
| 7895 ast_context()->ReturnValue(Pop()); |
| 7896 return true; |
| 7897 } |
| 7898 break; |
7510 default: | 7899 default: |
7511 // Not yet supported for inlining. | 7900 // Not yet supported for inlining. |
7512 break; | 7901 break; |
7513 } | 7902 } |
7514 return false; | 7903 return false; |
7515 } | 7904 } |
7516 | 7905 |
7517 | 7906 |
7518 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) { | 7907 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) { |
7519 Expression* callee = expr->expression(); | 7908 Expression* callee = expr->expression(); |
(...skipping 3128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10648 Zone* zone) { | 11037 Zone* zone) { |
10649 if (range != NULL && !range->IsEmpty()) { | 11038 if (range != NULL && !range->IsEmpty()) { |
10650 PrintIndent(); | 11039 PrintIndent(); |
10651 trace_.Add("%d %s", range->id(), type); | 11040 trace_.Add("%d %s", range->id(), type); |
10652 if (range->HasRegisterAssigned()) { | 11041 if (range->HasRegisterAssigned()) { |
10653 LOperand* op = range->CreateAssignedOperand(zone); | 11042 LOperand* op = range->CreateAssignedOperand(zone); |
10654 int assigned_reg = op->index(); | 11043 int assigned_reg = op->index(); |
10655 if (op->IsDoubleRegister()) { | 11044 if (op->IsDoubleRegister()) { |
10656 trace_.Add(" \"%s\"", | 11045 trace_.Add(" \"%s\"", |
10657 DoubleRegister::AllocationIndexToString(assigned_reg)); | 11046 DoubleRegister::AllocationIndexToString(assigned_reg)); |
| 11047 } else if (op->IsFloat32x4Register()) { |
| 11048 trace_.Add(" \"%s\"", |
| 11049 Float32x4Register::AllocationIndexToString(assigned_reg)); |
| 11050 } else if (op->IsInt32x4Register()) { |
| 11051 trace_.Add(" \"%s\"", |
| 11052 Int32x4Register::AllocationIndexToString(assigned_reg)); |
10658 } else { | 11053 } else { |
10659 ASSERT(op->IsRegister()); | 11054 ASSERT(op->IsRegister()); |
10660 trace_.Add(" \"%s\"", Register::AllocationIndexToString(assigned_reg)); | 11055 trace_.Add(" \"%s\"", Register::AllocationIndexToString(assigned_reg)); |
10661 } | 11056 } |
10662 } else if (range->IsSpilled()) { | 11057 } else if (range->IsSpilled()) { |
10663 LOperand* op = range->TopLevel()->GetSpillOperand(); | 11058 LOperand* op = range->TopLevel()->GetSpillOperand(); |
10664 if (op->IsDoubleStackSlot()) { | 11059 if (op->IsDoubleStackSlot()) { |
10665 trace_.Add(" \"double_stack:%d\"", op->index()); | 11060 trace_.Add(" \"double_stack:%d\"", op->index()); |
| 11061 } else if (op->IsFloat32x4StackSlot()) { |
| 11062 trace_.Add(" \"float32x4_stack:%d\"", op->index()); |
| 11063 } else if (op->IsInt32x4StackSlot()) { |
| 11064 trace_.Add(" \"int32x4_stack:%d\"", op->index()); |
10666 } else { | 11065 } else { |
10667 ASSERT(op->IsStackSlot()); | 11066 ASSERT(op->IsStackSlot()); |
10668 trace_.Add(" \"stack:%d\"", op->index()); | 11067 trace_.Add(" \"stack:%d\"", op->index()); |
10669 } | 11068 } |
10670 } | 11069 } |
10671 int parent_index = -1; | 11070 int parent_index = -1; |
10672 if (range->IsChild()) { | 11071 if (range->IsChild()) { |
10673 parent_index = range->parent()->id(); | 11072 parent_index = range->parent()->id(); |
10674 } else { | 11073 } else { |
10675 parent_index = range->id(); | 11074 parent_index = range->id(); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10785 if (ShouldProduceTraceOutput()) { | 11184 if (ShouldProduceTraceOutput()) { |
10786 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11185 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
10787 } | 11186 } |
10788 | 11187 |
10789 #ifdef DEBUG | 11188 #ifdef DEBUG |
10790 graph_->Verify(false); // No full verify. | 11189 graph_->Verify(false); // No full verify. |
10791 #endif | 11190 #endif |
10792 } | 11191 } |
10793 | 11192 |
10794 } } // namespace v8::internal | 11193 } } // namespace v8::internal |
OLD | NEW |