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

Side by Side Diff: src/hydrogen.cc

Issue 7170012: Crankshaft support for polymorphic array handling (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: address comments; add implemention for ARM and x64 Created 9 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
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 3431 matching lines...) Expand 10 before | Expand all | Expand 10 after
3442 instr = BuildStoreNamedGeneric(object, name, value); 3442 instr = BuildStoreNamedGeneric(object, name, value);
3443 } 3443 }
3444 3444
3445 } else { 3445 } else {
3446 // Keyed store. 3446 // Keyed store.
3447 CHECK_ALIVE(VisitForValue(prop->key())); 3447 CHECK_ALIVE(VisitForValue(prop->key()));
3448 CHECK_ALIVE(VisitForValue(expr->value())); 3448 CHECK_ALIVE(VisitForValue(expr->value()));
3449 value = Pop(); 3449 value = Pop();
3450 HValue* key = Pop(); 3450 HValue* key = Pop();
3451 HValue* object = Pop(); 3451 HValue* object = Pop();
3452 instr = BuildStoreKeyed(object, key, value, expr); 3452 bool has_side_effects = false;
3453 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(),
3454 expr->position(),
3455 true, // is_store
3456 &has_side_effects);
3457 Push(value);
3458 ASSERT(has_side_effects); // Stores always have side effects.
3459 AddSimulate(expr->AssignmentId());
3460 ast_context()->ReturnValue(Pop());
3461 return;
3453 } 3462 }
3454 Push(value); 3463 Push(value);
3455 instr->set_position(expr->position()); 3464 instr->set_position(expr->position());
3456 AddInstruction(instr); 3465 AddInstruction(instr);
3457 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); 3466 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3458 ast_context()->ReturnValue(Pop()); 3467 ast_context()->ReturnValue(Pop());
3459 } 3468 }
3460 3469
3461 3470
3462 // Because not every expression has a position and there is not common 3471 // Because not every expression has a position and there is not common
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
3566 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); 3575 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
3567 ast_context()->ReturnValue(Pop()); 3576 ast_context()->ReturnValue(Pop());
3568 3577
3569 } else { 3578 } else {
3570 // Keyed property. 3579 // Keyed property.
3571 CHECK_ALIVE(VisitForValue(prop->obj())); 3580 CHECK_ALIVE(VisitForValue(prop->obj()));
3572 CHECK_ALIVE(VisitForValue(prop->key())); 3581 CHECK_ALIVE(VisitForValue(prop->key()));
3573 HValue* obj = environment()->ExpressionStackAt(1); 3582 HValue* obj = environment()->ExpressionStackAt(1);
3574 HValue* key = environment()->ExpressionStackAt(0); 3583 HValue* key = environment()->ExpressionStackAt(0);
3575 3584
3576 HInstruction* load = BuildLoadKeyed(obj, key, prop); 3585 bool has_side_effects = false;
3577 PushAndAdd(load); 3586 HValue* load = HandleKeyedElementAccess(
3578 if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId()); 3587 obj, key, NULL, prop, expr->CompoundLoadId(), RelocInfo::kNoPosition,
3588 false, // is_store
3589 &has_side_effects);
3590 Push(load);
3591 if (has_side_effects) AddSimulate(expr->CompoundLoadId());
3592
3579 3593
3580 CHECK_ALIVE(VisitForValue(expr->value())); 3594 CHECK_ALIVE(VisitForValue(expr->value()));
3581 HValue* right = Pop(); 3595 HValue* right = Pop();
3582 HValue* left = Pop(); 3596 HValue* left = Pop();
3583 3597
3584 HInstruction* instr = BuildBinaryOperation(operation, left, right); 3598 HInstruction* instr = BuildBinaryOperation(operation, left, right);
3585 PushAndAdd(instr); 3599 PushAndAdd(instr);
3586 if (instr->HasSideEffects()) AddSimulate(operation->id()); 3600 if (instr->HasSideEffects()) AddSimulate(operation->id());
3587 3601
3588 expr->RecordTypeFeedback(oracle()); 3602 expr->RecordTypeFeedback(oracle());
3589 HInstruction* store = BuildStoreKeyed(obj, key, instr, expr); 3603 HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(),
3590 AddInstruction(store); 3604 RelocInfo::kNoPosition,
3605 true, // is_store
3606 &has_side_effects);
3607
3591 // Drop the simulated receiver, key, and value. Return the value. 3608 // Drop the simulated receiver, key, and value. Return the value.
3592 Drop(3); 3609 Drop(3);
3593 Push(instr); 3610 Push(instr);
3594 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); 3611 ASSERT(has_side_effects); // Stores always have side effects.
3612 AddSimulate(expr->AssignmentId());
3595 ast_context()->ReturnValue(Pop()); 3613 ast_context()->ReturnValue(Pop());
3596 } 3614 }
3597 3615
3598 } else { 3616 } else {
3599 return Bailout("invalid lhs in compound assignment"); 3617 return Bailout("invalid lhs in compound assignment");
3600 } 3618 }
3601 } 3619 }
3602 3620
3603 3621
3604 void HGraphBuilder::VisitAssignment(Assignment* expr) { 3622 void HGraphBuilder::VisitAssignment(Assignment* expr) {
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
3748 } 3766 }
3749 3767
3750 3768
3751 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, 3769 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
3752 HValue* key) { 3770 HValue* key) {
3753 HValue* context = environment()->LookupContext(); 3771 HValue* context = environment()->LookupContext();
3754 return new(zone()) HLoadKeyedGeneric(context, object, key); 3772 return new(zone()) HLoadKeyedGeneric(context, object, key);
3755 } 3773 }
3756 3774
3757 3775
3758 HInstruction* HGraphBuilder::BuildLoadKeyedFastElement(HValue* object, 3776 HInstruction* HGraphBuilder::BuildExternalArrayElementAccess(
3759 HValue* key, 3777 HValue* external_elements,
3760 Property* expr) { 3778 HValue* checked_key,
3761 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic()); 3779 HValue* val,
3780 JSObject::ElementsKind elements_kind,
3781 bool is_store) {
3782 if (is_store) {
3783 ASSERT(val != NULL);
3784 switch (elements_kind) {
3785 case JSObject::EXTERNAL_PIXEL_ELEMENTS: {
3786 HClampToUint8* clamp = new(zone()) HClampToUint8(val);
3787 AddInstruction(clamp);
3788 val = clamp;
3789 break;
3790 }
3791 case JSObject::EXTERNAL_BYTE_ELEMENTS:
3792 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3793 case JSObject::EXTERNAL_SHORT_ELEMENTS:
3794 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3795 case JSObject::EXTERNAL_INT_ELEMENTS:
3796 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: {
3797 HToInt32* floor_val = new(zone()) HToInt32(val);
3798 AddInstruction(floor_val);
3799 val = floor_val;
3800 break;
3801 }
3802 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
3803 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
3804 break;
3805 case JSObject::FAST_ELEMENTS:
3806 case JSObject::FAST_DOUBLE_ELEMENTS:
3807 case JSObject::DICTIONARY_ELEMENTS:
3808 UNREACHABLE();
3809 break;
3810 }
3811 return new(zone()) HStoreKeyedSpecializedArrayElement(
3812 external_elements, checked_key, val, elements_kind);
3813 } else {
3814 return new(zone()) HLoadKeyedSpecializedArrayElement(
3815 external_elements, checked_key, elements_kind);
3816 }
3817 }
3818
3819
3820 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object,
3821 HValue* key,
3822 HValue* val,
3823 Expression* expr,
3824 bool is_store) {
3825 ASSERT(expr->IsMonomorphic());
3826 Handle<Map> map = expr->GetMonomorphicReceiverType();
3827 if (!map->has_fast_elements() && !map->has_external_array_elements()) {
3828 return is_store ? BuildStoreKeyedGeneric(object, key, val)
3829 : BuildLoadKeyedGeneric(object, key);
3830 }
3762 AddInstruction(new(zone()) HCheckNonSmi(object)); 3831 AddInstruction(new(zone()) HCheckNonSmi(object));
3763 Handle<Map> map = expr->GetMonomorphicReceiverType();
3764 ASSERT(map->has_fast_elements());
3765 AddInstruction(new(zone()) HCheckMap(object, map)); 3832 AddInstruction(new(zone()) HCheckMap(object, map));
3766 bool is_array = (map->instance_type() == JS_ARRAY_TYPE); 3833 HInstruction* elements = new(zone()) HLoadElements(object);
3767 HLoadElements* elements = new(zone()) HLoadElements(object);
3768 HInstruction* length = NULL; 3834 HInstruction* length = NULL;
3769 HInstruction* checked_key = NULL; 3835 HInstruction* checked_key = NULL;
3770 if (is_array) { 3836 if (map->has_external_array_elements()) {
3837 AddInstruction(elements);
3838 length = AddInstruction(new(zone()) HExternalArrayLength(elements));
3839 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
3840 HLoadExternalArrayPointer* external_elements =
3841 new(zone()) HLoadExternalArrayPointer(elements);
3842 AddInstruction(external_elements);
3843 return BuildExternalArrayElementAccess(external_elements, checked_key,
3844 val, map->elements_kind(), is_store);
3845 }
3846 ASSERT(map->has_fast_elements());
3847 if (map->instance_type() == JS_ARRAY_TYPE) {
3771 length = AddInstruction(new(zone()) HJSArrayLength(object)); 3848 length = AddInstruction(new(zone()) HJSArrayLength(object));
3772 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); 3849 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
3773 AddInstruction(elements); 3850 AddInstruction(elements);
3774 } else { 3851 } else {
3775 AddInstruction(elements); 3852 AddInstruction(elements);
3776 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); 3853 length = AddInstruction(new(zone()) HFixedArrayLength(elements));
3777 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); 3854 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
3778 } 3855 }
3779 return new(zone()) HLoadKeyedFastElement(elements, checked_key); 3856 if (is_store) {
3857 return new(zone()) HStoreKeyedFastElement(elements, checked_key, val);
3858 } else {
3859 return new(zone()) HLoadKeyedFastElement(elements, checked_key);
3860 }
3780 } 3861 }
3781 3862
3782 3863
3783 HInstruction* HGraphBuilder::BuildLoadKeyedSpecializedArrayElement( 3864 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
3784 HValue* object, 3865 HValue* key,
3785 HValue* key, 3866 HValue* val,
3786 Property* expr) { 3867 Expression* prop,
3787 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic()); 3868 int ast_id,
3869 int position,
3870 bool is_store,
3871 bool* has_side_effects) {
3872 *has_side_effects = false;
3788 AddInstruction(new(zone()) HCheckNonSmi(object)); 3873 AddInstruction(new(zone()) HCheckNonSmi(object));
3789 Handle<Map> map = expr->GetMonomorphicReceiverType(); 3874 AddInstruction(HCheckInstanceType::NewIsSpecObject(object));
3790 ASSERT(!map->has_fast_elements()); 3875 ZoneMapList* maps = prop->GetReceiverTypes();
3791 ASSERT(map->has_external_array_elements()); 3876 bool todo_external_array = false;
3792 AddInstruction(new(zone()) HCheckMap(object, map)); 3877
3793 HLoadElements* elements = new(zone()) HLoadElements(object); 3878 static const int kNumElementTypes = JSObject::kElementsKindCount;
3794 AddInstruction(elements); 3879 bool type_todo[kNumElementTypes];
3795 HInstruction* length = new(zone()) HExternalArrayLength(elements); 3880 for (int i = 0; i < kNumElementTypes; ++i) {
3796 AddInstruction(length); 3881 type_todo[i] = false;
3797 HInstruction* checked_key = 3882 }
3798 AddInstruction(new(zone()) HBoundsCheck(key, length)); 3883
3799 HLoadExternalArrayPointer* external_elements = 3884 for (int i = 0; i < maps->length(); ++i) {
3800 new(zone()) HLoadExternalArrayPointer(elements); 3885 ASSERT(maps->at(i)->IsMap());
3801 AddInstruction(external_elements); 3886 type_todo[maps->at(i)->elements_kind()] = true;
3802 HLoadKeyedSpecializedArrayElement* pixel_array_value = 3887 if (maps->at(i)->elements_kind()
3803 new(zone()) HLoadKeyedSpecializedArrayElement( 3888 >= JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) {
3804 external_elements, checked_key, map->elements_kind()); 3889 todo_external_array = true;
3805 return pixel_array_value; 3890 }
3891 }
3892 // We can't treat dictionary elements here (need to deopt instead).
3893 type_todo[JSObject::DICTIONARY_ELEMENTS] = false;
3894 // Support for FAST_DOUBLE_ELEMENTS isn't implemented yet, so we deopt.
3895 type_todo[JSObject::FAST_DOUBLE_ELEMENTS] = false;
3896
3897 HBasicBlock* join = graph()->CreateBasicBlock();
3898
3899 HInstruction* elements_kind_instr =
3900 AddInstruction(new(zone()) HElementsKind(object));
3901 HInstruction* elements = NULL;
3902 HLoadExternalArrayPointer* external_elements = NULL;
3903 HInstruction* checked_key = NULL;
3904
3905 // FAST_ELEMENTS is assumed to be the first case.
3906 STATIC_ASSERT(JSObject::FAST_ELEMENTS == 0);
3907
3908 for (JSObject::ElementsKind elements_kind = JSObject::FAST_ELEMENTS;
3909 elements_kind <= JSObject::LAST_ELEMENTS_KIND;
3910 elements_kind = JSObject::ElementsKind(elements_kind + 1)) {
3911 // After having handled FAST_ELEMENTS in the first run of the loop, we
3912 // need to add some code that's executed for all other cases.
3913 if (elements_kind == 1 && todo_external_array) {
Søren Thygesen Gjesse 2011/06/21 07:09:04 Shouldn't the constant 1 here be JSObject::FAST_EL
Jakob Kummerow 2011/06/21 07:49:23 No. FAST_ELEMENTS == 0. As the comment indicates,
Søren Thygesen Gjesse 2011/06/21 10:01:53 I see. I think it should stay at the beginning of
3914 elements = AddInstruction(new(zone()) HLoadElements(object));
3915 // We need to forcibly prevent some ElementsKind-dependent instructions
3916 // from being hoisted out of any loops they might occur in, because
3917 // the current loop-invariant-code-motion algorithm isn't clever enough
3918 // to deal with them properly.
3919 // There's some performance to be gained by developing a smarter
3920 // solution for this.
3921 elements->ClearFlag(HValue::kUseGVN);
3922 HInstruction* length =
3923 AddInstruction(new(zone()) HExternalArrayLength(elements));
3924 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
3925 external_elements = new(zone()) HLoadExternalArrayPointer(elements);
3926 AddInstruction(external_elements);
3927 }
3928 if (type_todo[elements_kind]) {
3929 HBasicBlock* if_true = graph()->CreateBasicBlock();
3930 HBasicBlock* if_false = graph()->CreateBasicBlock();
3931 HCompareConstantEq* compare = new(zone()) HCompareConstantEq(
3932 elements_kind_instr,
3933 elements_kind,
3934 Token::EQ_STRICT);
3935 AddInstruction(compare);
3936 HTest* branch = new(zone()) HTest(compare, if_true, if_false);
3937 current_block()->Finish(branch);
3938
3939 set_current_block(if_true);
3940 HInstruction* access;
3941 if (elements_kind == JSObject::FAST_ELEMENTS) {
3942 HBasicBlock* if_jsarray = graph()->CreateBasicBlock();
3943 HBasicBlock* if_fastobject = graph()->CreateBasicBlock();
3944 HInstruction* typecheck =
3945 AddInstruction(new(zone()) HHasInstanceType(object, JS_ARRAY_TYPE));
3946 HTest* test = new(zone()) HTest(typecheck, if_jsarray, if_fastobject);
3947 current_block()->Finish(test);
3948
3949 set_current_block(if_jsarray);
3950 HInstruction* length = new(zone()) HJSArrayLength(object);
3951 AddInstruction(length);
3952 length->ClearFlag(HValue::kUseGVN);
3953 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
3954 elements = AddInstruction(new(zone()) HLoadElements(object));
3955 elements->ClearFlag(HValue::kUseGVN);
3956 if (is_store) {
3957 access = AddInstruction(
3958 new(zone()) HStoreKeyedFastElement(elements, checked_key, val));
3959 } else {
3960 access = AddInstruction(
3961 new(zone()) HLoadKeyedFastElement(elements, checked_key));
3962 Push(access);
3963 }
3964 *has_side_effects |= access->HasSideEffects();
3965 if (position != -1) {
3966 access->set_position(position);
3967 }
3968 if_jsarray->Goto(join);
3969
3970 set_current_block(if_fastobject);
3971 elements = AddInstruction(new(zone()) HLoadElements(object));
3972 elements->ClearFlag(HValue::kUseGVN);
3973 length = AddInstruction(new(zone()) HFixedArrayLength(elements));
3974 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
3975 if (is_store) {
3976 access = AddInstruction(
3977 new(zone()) HStoreKeyedFastElement(elements, checked_key, val));
3978 } else {
3979 access = AddInstruction(
3980 new(zone()) HLoadKeyedFastElement(elements, checked_key));
3981 }
3982 } else { // External array elements.
3983 access = AddInstruction(BuildExternalArrayElementAccess(
3984 external_elements, checked_key, val, elements_kind, is_store));
3985 }
3986 *has_side_effects |= access->HasSideEffects();
3987 access->set_position(position);
3988 if (!is_store) {
3989 Push(access);
3990 }
3991 current_block()->Goto(join);
3992 set_current_block(if_false);
3993 }
3994 }
3995
3996 // Deopt if none of the cases matched.
3997 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses);
3998 join->SetJoinId(ast_id);
3999 set_current_block(join);
4000 return is_store ? NULL : Pop();
3806 } 4001 }
3807 4002
3808 4003
3809 HInstruction* HGraphBuilder::BuildLoadKeyed(HValue* obj, 4004 HValue* HGraphBuilder::HandleKeyedElementAccess(HValue* obj,
3810 HValue* key, 4005 HValue* key,
3811 Property* prop) { 4006 HValue* val,
3812 if (prop->IsMonomorphic()) { 4007 Expression* expr,
3813 Handle<Map> receiver_type(prop->GetMonomorphicReceiverType()); 4008 int ast_id,
3814 // An object has either fast elements or pixel array elements, but never 4009 int position,
3815 // both. Pixel array maps that are assigned to pixel array elements are 4010 bool is_store,
3816 // always created with the fast elements flag cleared. 4011 bool* has_side_effects) {
3817 if (receiver_type->has_external_array_elements()) { 4012 ASSERT(!expr->IsPropertyName());
3818 return BuildLoadKeyedSpecializedArrayElement(obj, key, prop); 4013 HInstruction* instr = NULL;
3819 } else if (receiver_type->has_fast_elements()) { 4014 if (expr->IsMonomorphic()) {
3820 return BuildLoadKeyedFastElement(obj, key, prop); 4015 instr = BuildMonomorphicElementAccess(obj, key, val, expr, is_store);
4016 } else if (expr->GetReceiverTypes() != NULL &&
4017 !expr->GetReceiverTypes()->is_empty()) {
4018 return HandlePolymorphicElementAccess(
4019 obj, key, val, expr, ast_id, position, is_store, has_side_effects);
4020 } else {
4021 if (is_store) {
4022 instr = BuildStoreKeyedGeneric(obj, key, val);
4023 } else {
4024 instr = BuildLoadKeyedGeneric(obj, key);
3821 } 4025 }
3822 } 4026 }
3823 return BuildLoadKeyedGeneric(obj, key); 4027 instr->set_position(position);
4028 AddInstruction(instr);
4029 *has_side_effects = instr->HasSideEffects();
4030 return instr;
3824 } 4031 }
3825 4032
3826 4033
3827 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object, 4034 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object,
3828 HValue* key, 4035 HValue* key,
3829 HValue* value) { 4036 HValue* value) {
3830 HValue* context = environment()->LookupContext(); 4037 HValue* context = environment()->LookupContext();
3831 return new(zone()) HStoreKeyedGeneric( 4038 return new(zone()) HStoreKeyedGeneric(
3832 context, 4039 context,
3833 object, 4040 object,
3834 key, 4041 key,
3835 value, 4042 value,
3836 function_strict_mode()); 4043 function_strict_mode());
3837 } 4044 }
3838 4045
3839
3840 HInstruction* HGraphBuilder::BuildStoreKeyedFastElement(HValue* object,
3841 HValue* key,
3842 HValue* val,
3843 Expression* expr) {
3844 ASSERT(expr->IsMonomorphic());
3845 AddInstruction(new(zone()) HCheckNonSmi(object));
3846 Handle<Map> map = expr->GetMonomorphicReceiverType();
3847 ASSERT(map->has_fast_elements());
3848 AddInstruction(new(zone()) HCheckMap(object, map));
3849 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object));
3850 AddInstruction(new(zone()) HCheckMap(
3851 elements, isolate()->factory()->fixed_array_map()));
3852 bool is_array = (map->instance_type() == JS_ARRAY_TYPE);
3853 HInstruction* length = NULL;
3854 if (is_array) {
3855 length = AddInstruction(new(zone()) HJSArrayLength(object));
3856 } else {
3857 length = AddInstruction(new(zone()) HFixedArrayLength(elements));
3858 }
3859 HInstruction* checked_key =
3860 AddInstruction(new(zone()) HBoundsCheck(key, length));
3861 return new(zone()) HStoreKeyedFastElement(elements, checked_key, val);
3862 }
3863
3864
3865 HInstruction* HGraphBuilder::BuildStoreKeyedSpecializedArrayElement(
3866 HValue* object,
3867 HValue* key,
3868 HValue* val,
3869 Expression* expr) {
3870 ASSERT(expr->IsMonomorphic());
3871 AddInstruction(new(zone()) HCheckNonSmi(object));
3872 Handle<Map> map = expr->GetMonomorphicReceiverType();
3873 ASSERT(!map->has_fast_elements());
3874 ASSERT(map->has_external_array_elements());
3875 AddInstruction(new(zone()) HCheckMap(object, map));
3876 HLoadElements* elements = new(zone()) HLoadElements(object);
3877 AddInstruction(elements);
3878 HInstruction* length = AddInstruction(
3879 new(zone()) HExternalArrayLength(elements));
3880 HInstruction* checked_key =
3881 AddInstruction(new(zone()) HBoundsCheck(key, length));
3882 HLoadExternalArrayPointer* external_elements =
3883 new(zone()) HLoadExternalArrayPointer(elements);
3884 AddInstruction(external_elements);
3885 JSObject::ElementsKind elements_kind = map->elements_kind();
3886 switch (elements_kind) {
3887 case JSObject::EXTERNAL_PIXEL_ELEMENTS: {
3888 HClampToUint8* clamp = new(zone()) HClampToUint8(val);
3889 AddInstruction(clamp);
3890 val = clamp;
3891 break;
3892 }
3893 case JSObject::EXTERNAL_BYTE_ELEMENTS:
3894 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3895 case JSObject::EXTERNAL_SHORT_ELEMENTS:
3896 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3897 case JSObject::EXTERNAL_INT_ELEMENTS:
3898 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: {
3899 HToInt32* floor_val = new(zone()) HToInt32(val);
3900 AddInstruction(floor_val);
3901 val = floor_val;
3902 break;
3903 }
3904 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
3905 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
3906 break;
3907
3908 case JSObject::FAST_ELEMENTS:
3909 case JSObject::FAST_DOUBLE_ELEMENTS:
3910 case JSObject::DICTIONARY_ELEMENTS:
3911 UNREACHABLE();
3912 break;
3913 }
3914 return new(zone()) HStoreKeyedSpecializedArrayElement(
3915 external_elements,
3916 checked_key,
3917 val,
3918 map->elements_kind());
3919 }
3920
3921
3922 HInstruction* HGraphBuilder::BuildStoreKeyed(HValue* object,
3923 HValue* key,
3924 HValue* value,
3925 Expression* expr) {
3926 if (expr->IsMonomorphic()) {
3927 Handle<Map> receiver_type(expr->GetMonomorphicReceiverType());
3928 // An object has either fast elements or external array elements, but
3929 // never both. Pixel array maps that are assigned to pixel array elements
3930 // are always created with the fast elements flag cleared.
3931 if (receiver_type->has_external_array_elements()) {
3932 return BuildStoreKeyedSpecializedArrayElement(object,
3933 key,
3934 value,
3935 expr);
3936 } else if (receiver_type->has_fast_elements()) {
3937 return BuildStoreKeyedFastElement(object, key, value, expr);
3938 }
3939 }
3940 return BuildStoreKeyedGeneric(object, key, value);
3941 }
3942
3943
3944 bool HGraphBuilder::TryArgumentsAccess(Property* expr) { 4046 bool HGraphBuilder::TryArgumentsAccess(Property* expr) {
3945 VariableProxy* proxy = expr->obj()->AsVariableProxy(); 4047 VariableProxy* proxy = expr->obj()->AsVariableProxy();
3946 if (proxy == NULL) return false; 4048 if (proxy == NULL) return false;
3947 if (!proxy->var()->IsStackAllocated()) return false; 4049 if (!proxy->var()->IsStackAllocated()) return false;
3948 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { 4050 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
3949 return false; 4051 return false;
3950 } 4052 }
3951 4053
3952 // Our implementation of arguments (based on this stack frame or an 4054 // Our implementation of arguments (based on this stack frame or an
3953 // adapter below it) does not work for inlined functions. 4055 // adapter below it) does not work for inlined functions.
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
4027 instr = new(zone()) HLoadNamedFieldPolymorphic(obj, types, name); 4129 instr = new(zone()) HLoadNamedFieldPolymorphic(obj, types, name);
4028 } else { 4130 } else {
4029 instr = BuildLoadNamedGeneric(obj, expr); 4131 instr = BuildLoadNamedGeneric(obj, expr);
4030 } 4132 }
4031 4133
4032 } else { 4134 } else {
4033 CHECK_ALIVE(VisitForValue(expr->key())); 4135 CHECK_ALIVE(VisitForValue(expr->key()));
4034 4136
4035 HValue* key = Pop(); 4137 HValue* key = Pop();
4036 HValue* obj = Pop(); 4138 HValue* obj = Pop();
4037 instr = BuildLoadKeyed(obj, key, expr); 4139
4140 bool has_side_effects = false;
4141 HValue* load = HandleKeyedElementAccess(
4142 obj, key, NULL, expr, expr->id(), expr->position(),
4143 false, // is_store
4144 &has_side_effects);
4145 if (has_side_effects) {
4146 if (ast_context()->IsEffect()) {
4147 AddSimulate(expr->id());
4148 } else {
4149 Push(load);
4150 AddSimulate(expr->id());
4151 Drop(1);
4152 }
4153 }
4154 ast_context()->ReturnValue(load);
4155 return;
4038 } 4156 }
4039 instr->set_position(expr->position()); 4157 instr->set_position(expr->position());
4040 ast_context()->ReturnInstruction(instr, expr->id()); 4158 ast_context()->ReturnInstruction(instr, expr->id());
4041 } 4159 }
4042 4160
4043 4161
4044 void HGraphBuilder::AddCheckConstantFunction(Call* expr, 4162 void HGraphBuilder::AddCheckConstantFunction(Call* expr,
4045 HValue* receiver, 4163 HValue* receiver,
4046 Handle<Map> receiver_map, 4164 Handle<Map> receiver_map,
4047 bool smi_and_map_check) { 4165 bool smi_and_map_check) {
(...skipping 989 matching lines...) Expand 10 before | Expand all | Expand 10 after
5037 5155
5038 } else { 5156 } else {
5039 // Keyed property. 5157 // Keyed property.
5040 if (returns_original_input) Push(graph_->GetConstantUndefined()); 5158 if (returns_original_input) Push(graph_->GetConstantUndefined());
5041 5159
5042 CHECK_ALIVE(VisitForValue(prop->obj())); 5160 CHECK_ALIVE(VisitForValue(prop->obj()));
5043 CHECK_ALIVE(VisitForValue(prop->key())); 5161 CHECK_ALIVE(VisitForValue(prop->key()));
5044 HValue* obj = environment()->ExpressionStackAt(1); 5162 HValue* obj = environment()->ExpressionStackAt(1);
5045 HValue* key = environment()->ExpressionStackAt(0); 5163 HValue* key = environment()->ExpressionStackAt(0);
5046 5164
5047 HInstruction* load = BuildLoadKeyed(obj, key, prop); 5165 bool has_side_effects = false;
5048 PushAndAdd(load); 5166 HValue* load = HandleKeyedElementAccess(
5049 if (load->HasSideEffects()) AddSimulate(expr->CountId()); 5167 obj, key, NULL, prop, expr->CountId(), RelocInfo::kNoPosition,
5168 false, // is_store
5169 &has_side_effects);
5170 Push(load);
5171 if (has_side_effects) AddSimulate(expr->CountId());
5050 5172
5051 after = BuildIncrement(returns_original_input, expr); 5173 after = BuildIncrement(returns_original_input, expr);
5052 input = Pop(); 5174 input = Pop();
5053 5175
5054 expr->RecordTypeFeedback(oracle()); 5176 expr->RecordTypeFeedback(oracle());
5055 HInstruction* store = BuildStoreKeyed(obj, key, after, expr); 5177 HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(),
5056 AddInstruction(store); 5178 RelocInfo::kNoPosition,
5179 true, // is_store
5180 &has_side_effects);
5057 5181
5058 // Drop the key from the bailout environment. Overwrite the receiver 5182 // Drop the key from the bailout environment. Overwrite the receiver
5059 // with the result of the operation, and the placeholder with the 5183 // with the result of the operation, and the placeholder with the
5060 // original value if necessary. 5184 // original value if necessary.
5061 Drop(1); 5185 Drop(1);
5062 environment()->SetExpressionStackAt(0, after); 5186 environment()->SetExpressionStackAt(0, after);
5063 if (returns_original_input) environment()->SetExpressionStackAt(1, input); 5187 if (returns_original_input) environment()->SetExpressionStackAt(1, input);
5064 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); 5188 ASSERT(has_side_effects); // Stores always have side effects.
5189 AddSimulate(expr->AssignmentId());
5065 } 5190 }
5066 } 5191 }
5067 5192
5068 Drop(returns_original_input ? 2 : 1); 5193 Drop(returns_original_input ? 2 : 1);
5069 ast_context()->ReturnValue(expr->is_postfix() ? input : after); 5194 ast_context()->ReturnValue(expr->is_postfix() ? input : after);
5070 } 5195 }
5071 5196
5072 5197
5073 HCompareSymbolEq* HGraphBuilder::BuildSymbolCompare(HValue* left, 5198 HCompareSymbolEq* HGraphBuilder::BuildSymbolCompare(HValue* left,
5074 HValue* right, 5199 HValue* right,
(...skipping 1332 matching lines...) Expand 10 before | Expand all | Expand 10 after
6407 } 6532 }
6408 } 6533 }
6409 6534
6410 #ifdef DEBUG 6535 #ifdef DEBUG
6411 if (graph_ != NULL) graph_->Verify(); 6536 if (graph_ != NULL) graph_->Verify();
6412 if (allocator_ != NULL) allocator_->Verify(); 6537 if (allocator_ != NULL) allocator_->Verify();
6413 #endif 6538 #endif
6414 } 6539 }
6415 6540
6416 } } // namespace v8::internal 6541 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | src/objects-inl.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698