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

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 Florian's comments 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
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 if (has_side_effects) AddSimulate(expr->AssignmentId());
3459 ast_context()->ReturnValue(Pop());
3460 return;
3453 } 3461 }
3454 Push(value); 3462 Push(value);
3455 instr->set_position(expr->position()); 3463 instr->set_position(expr->position());
3456 AddInstruction(instr); 3464 AddInstruction(instr);
3457 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); 3465 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3458 ast_context()->ReturnValue(Pop()); 3466 ast_context()->ReturnValue(Pop());
3459 } 3467 }
3460 3468
3461 3469
3462 // Because not every expression has a position and there is not common 3470 // 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()); 3574 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
3567 ast_context()->ReturnValue(Pop()); 3575 ast_context()->ReturnValue(Pop());
3568 3576
3569 } else { 3577 } else {
3570 // Keyed property. 3578 // Keyed property.
3571 CHECK_ALIVE(VisitForValue(prop->obj())); 3579 CHECK_ALIVE(VisitForValue(prop->obj()));
3572 CHECK_ALIVE(VisitForValue(prop->key())); 3580 CHECK_ALIVE(VisitForValue(prop->key()));
3573 HValue* obj = environment()->ExpressionStackAt(1); 3581 HValue* obj = environment()->ExpressionStackAt(1);
3574 HValue* key = environment()->ExpressionStackAt(0); 3582 HValue* key = environment()->ExpressionStackAt(0);
3575 3583
3576 HInstruction* load = BuildLoadKeyed(obj, key, prop); 3584 bool has_side_effects = false;
3577 PushAndAdd(load); 3585 HValue* load = HandleKeyedElementAccess(
3578 if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId()); 3586 obj, key, NULL, prop, expr->CompoundLoadId(), -1,
3587 false, // is_store
3588 &has_side_effects);
3589 Push(load);
3590 if (has_side_effects) AddSimulate(expr->CompoundLoadId());
3591
3579 3592
3580 CHECK_ALIVE(VisitForValue(expr->value())); 3593 CHECK_ALIVE(VisitForValue(expr->value()));
3581 HValue* right = Pop(); 3594 HValue* right = Pop();
3582 HValue* left = Pop(); 3595 HValue* left = Pop();
3583 3596
3584 HInstruction* instr = BuildBinaryOperation(operation, left, right); 3597 HInstruction* instr = BuildBinaryOperation(operation, left, right);
3585 PushAndAdd(instr); 3598 PushAndAdd(instr);
3586 if (instr->HasSideEffects()) AddSimulate(operation->id()); 3599 if (instr->HasSideEffects()) AddSimulate(operation->id());
3587 3600
3588 expr->RecordTypeFeedback(oracle()); 3601 expr->RecordTypeFeedback(oracle());
3589 HInstruction* store = BuildStoreKeyed(obj, key, instr, expr); 3602 HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(), -1,
3590 AddInstruction(store); 3603 true, // is_store
3604 &has_side_effects);
3605
3591 // Drop the simulated receiver, key, and value. Return the value. 3606 // Drop the simulated receiver, key, and value. Return the value.
3592 Drop(3); 3607 Drop(3);
3593 Push(instr); 3608 Push(instr);
3594 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); 3609 if (has_side_effects) AddSimulate(expr->AssignmentId());
3595 ast_context()->ReturnValue(Pop()); 3610 ast_context()->ReturnValue(Pop());
3596 } 3611 }
3597 3612
3598 } else { 3613 } else {
3599 return Bailout("invalid lhs in compound assignment"); 3614 return Bailout("invalid lhs in compound assignment");
3600 } 3615 }
3601 } 3616 }
3602 3617
3603 3618
3604 void HGraphBuilder::VisitAssignment(Assignment* expr) { 3619 void HGraphBuilder::VisitAssignment(Assignment* expr) {
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
3748 } 3763 }
3749 3764
3750 3765
3751 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, 3766 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
3752 HValue* key) { 3767 HValue* key) {
3753 HValue* context = environment()->LookupContext(); 3768 HValue* context = environment()->LookupContext();
3754 return new(zone()) HLoadKeyedGeneric(context, object, key); 3769 return new(zone()) HLoadKeyedGeneric(context, object, key);
3755 } 3770 }
3756 3771
3757 3772
3758 HInstruction* HGraphBuilder::BuildLoadKeyedFastElement(HValue* object, 3773 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object,
3759 HValue* key, 3774 HValue* key,
3760 Property* expr) { 3775 HValue* val,
3761 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic()); 3776 Expression* expr,
3777 bool is_store) {
3778 ASSERT(expr->IsMonomorphic());
3779 Handle<Map> map = expr->GetMonomorphicReceiverType();
3780 if (!map->has_fast_elements() && !map->has_external_array_elements()) {
3781 if (is_store) {
fschneider 2011/06/16 13:21:28 maybe shorten to: return is_store ? BuildStoreKey
Jakob Kummerow 2011/06/17 08:06:09 Done.
3782 return BuildStoreKeyedGeneric(object, key, val);
3783 } else {
3784 return BuildLoadKeyedGeneric(object, key);
3785 }
3786 }
3762 AddInstruction(new(zone()) HCheckNonSmi(object)); 3787 AddInstruction(new(zone()) HCheckNonSmi(object));
3763 Handle<Map> map = expr->GetMonomorphicReceiverType();
3764 ASSERT(map->has_fast_elements());
3765 AddInstruction(new(zone()) HCheckMap(object, map)); 3788 AddInstruction(new(zone()) HCheckMap(object, map));
3766 bool is_array = (map->instance_type() == JS_ARRAY_TYPE); 3789 HInstruction* elements = new(zone()) HLoadElements(object);
3767 HLoadElements* elements = new(zone()) HLoadElements(object);
3768 HInstruction* length = NULL; 3790 HInstruction* length = NULL;
3769 HInstruction* checked_key = NULL; 3791 HInstruction* checked_key = NULL;
3770 if (is_array) { 3792 if (map->has_external_array_elements()) {
3793 AddInstruction(elements);
3794 length = AddInstruction(new(zone()) HExternalArrayLength(elements));
3795 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
3796 HLoadExternalArrayPointer* external_elements =
3797 new(zone()) HLoadExternalArrayPointer(elements);
3798 AddInstruction(external_elements);
3799 JSObject::ElementsKind elements_kind = map->elements_kind();
3800 if (is_store) {
3801 ASSERT(val != NULL);
3802 switch (elements_kind) {
3803 case JSObject::EXTERNAL_PIXEL_ELEMENTS: {
3804 HClampToUint8* clamp = new(zone()) HClampToUint8(val);
3805 AddInstruction(clamp);
3806 val = clamp;
3807 break;
3808 }
3809 case JSObject::EXTERNAL_BYTE_ELEMENTS:
3810 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3811 case JSObject::EXTERNAL_SHORT_ELEMENTS:
3812 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3813 case JSObject::EXTERNAL_INT_ELEMENTS:
3814 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: {
3815 HToInt32* floor_val = new(zone()) HToInt32(val);
3816 AddInstruction(floor_val);
3817 val = floor_val;
3818 break;
3819 }
3820 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
3821 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
3822 break;
3823 case JSObject::FAST_ELEMENTS:
3824 case JSObject::FAST_DOUBLE_ELEMENTS:
3825 case JSObject::DICTIONARY_ELEMENTS:
3826 UNREACHABLE();
3827 break;
3828 }
3829 return new(zone()) HStoreKeyedSpecializedArrayElement(
3830 external_elements, checked_key, val, elements_kind);
3831 } else {
3832 return new(zone()) HLoadKeyedSpecializedArrayElement(
3833 external_elements, checked_key, elements_kind);
3834 }
3835 }
3836 ASSERT(map->has_fast_elements());
3837 if (map->instance_type() == JS_ARRAY_TYPE) {
3771 length = AddInstruction(new(zone()) HJSArrayLength(object)); 3838 length = AddInstruction(new(zone()) HJSArrayLength(object));
3772 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); 3839 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
3773 AddInstruction(elements); 3840 AddInstruction(elements);
3774 } else { 3841 } else {
3775 AddInstruction(elements); 3842 AddInstruction(elements);
3776 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); 3843 length = AddInstruction(new(zone()) HFixedArrayLength(elements));
3777 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); 3844 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
3778 } 3845 }
3779 return new(zone()) HLoadKeyedFastElement(elements, checked_key); 3846 if (is_store) {
3780 } 3847 return new(zone()) HStoreKeyedFastElement(elements, checked_key, val);
3781 3848 } else {
3782 3849 return new(zone()) HLoadKeyedFastElement(elements, checked_key);
3783 HInstruction* HGraphBuilder::BuildLoadKeyedSpecializedArrayElement( 3850 }
3784 HValue* object, 3851 }
3785 HValue* key, 3852
3786 Property* expr) { 3853
3787 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic()); 3854 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
3855 HValue* key,
fschneider 2011/06/16 13:21:28 Align parameters in it fits 80 chars or else newli
Jakob Kummerow 2011/06/17 08:06:09 Done.
3856 HValue* val,
3857 Expression* prop,
3858 int ast_id,
3859 int position,
3860 bool is_store,
3861 bool* has_side_effects) {
3862 *has_side_effects = false;
3788 AddInstruction(new(zone()) HCheckNonSmi(object)); 3863 AddInstruction(new(zone()) HCheckNonSmi(object));
3789 Handle<Map> map = expr->GetMonomorphicReceiverType(); 3864 AddInstruction(HCheckInstanceType::NewIsSpecObject(object));
3790 ASSERT(!map->has_fast_elements()); 3865 ZoneMapList* maps = prop->GetReceiverTypes();
3791 ASSERT(map->has_external_array_elements()); 3866 bool todo_external_array = false;
3792 AddInstruction(new(zone()) HCheckMap(object, map)); 3867
3793 HLoadElements* elements = new(zone()) HLoadElements(object); 3868 static const int kNumElementTypes = JSObject::kElementsKindCount;
3794 AddInstruction(elements); 3869 bool type_todo[kNumElementTypes];
3795 HInstruction* length = new(zone()) HExternalArrayLength(elements); 3870 for (int i = 0; i < kNumElementTypes; ++i) {
3796 AddInstruction(length); 3871 type_todo[i] = false;
3797 HInstruction* checked_key = 3872 }
3798 AddInstruction(new(zone()) HBoundsCheck(key, length)); 3873
3799 HLoadExternalArrayPointer* external_elements = 3874 for (int i = 0; i < maps->length(); ++i) {
3800 new(zone()) HLoadExternalArrayPointer(elements); 3875 ASSERT(maps->at(i)->IsMap());
3801 AddInstruction(external_elements); 3876 type_todo[maps->at(i)->elements_kind()] = true;
3802 HLoadKeyedSpecializedArrayElement* pixel_array_value = 3877 if (maps->at(i)->elements_kind()
3803 new(zone()) HLoadKeyedSpecializedArrayElement( 3878 >= JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) {
3804 external_elements, checked_key, map->elements_kind()); 3879 todo_external_array = true;
3805 return pixel_array_value; 3880 }
3806 } 3881 }
3807 3882 // We can't treat dictionary elements here (need to deopt instead).
3808 3883 type_todo[JSObject::DICTIONARY_ELEMENTS] = false;
3809 HInstruction* HGraphBuilder::BuildLoadKeyed(HValue* obj, 3884
3810 HValue* key, 3885 HBasicBlock* join = graph()->CreateBasicBlock();
3811 Property* prop) { 3886
3812 if (prop->IsMonomorphic()) { 3887 HInstruction* elements_kind_instr =
3813 Handle<Map> receiver_type(prop->GetMonomorphicReceiverType()); 3888 AddInstruction(new(zone()) HElementsKind(object));
3814 // An object has either fast elements or pixel array elements, but never 3889 HInstruction* elements = NULL;
3815 // both. Pixel array maps that are assigned to pixel array elements are 3890 HLoadExternalArrayPointer* external_elements = NULL;
3816 // always created with the fast elements flag cleared. 3891 HInstruction* checked_key = NULL;
3817 if (receiver_type->has_external_array_elements()) { 3892
3818 return BuildLoadKeyedSpecializedArrayElement(obj, key, prop); 3893 // FAST_ELEMENTS is assumed to be the first case.
3819 } else if (receiver_type->has_fast_elements()) { 3894 STATIC_ASSERT(JSObject::FAST_ELEMENTS == 0);
3820 return BuildLoadKeyedFastElement(obj, key, prop); 3895
3821 } 3896 for (JSObject::ElementsKind elements_kind = JSObject::FAST_ELEMENTS;
3822 } 3897 elements_kind <= JSObject::LAST_ELEMENTS_KIND;
3823 return BuildLoadKeyedGeneric(obj, key); 3898 elements_kind = JSObject::ElementsKind(elements_kind + 1)) {
fschneider 2011/06/16 13:21:28 Too bad that ++ doesn't work ;)
Jakob Kummerow 2011/06/17 08:06:09 Yeah...
3899 // After having handled FAST_ELEMENTS in the first run of the loop, we
3900 // need to add some code that's executed for all other cases.
3901 if (elements_kind == 1 && todo_external_array) {
fschneider 2011/06/16 13:21:28 Maybe write if (elements_kind > JSObject::FAST_E
Jakob Kummerow 2011/06/17 08:06:09 No, because I only want to execute this if-block o
3902 elements = AddInstruction(new(zone()) HLoadElements(object));
3903 // We need to forcibly prevent some ElementsKind-dependent instructions
3904 // from being hoisted out of any loops they might occur in, because
3905 // the current loop-invariant-code-motion algorithm isn't clever enough
3906 // to deal with them properly.
3907 // There's some performance to be gained by developing a smarter
3908 // solution for this.
3909 elements->ClearFlag(HValue::kUseGVN);
3910 HInstruction* length =
3911 AddInstruction(new(zone()) HExternalArrayLength(elements));
3912 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
3913 external_elements = new(zone()) HLoadExternalArrayPointer(elements);
3914 AddInstruction(external_elements);
3915 }
3916 if (type_todo[elements_kind]) {
3917 HBasicBlock* if_true = graph()->CreateBasicBlock();
3918 HBasicBlock* if_false = graph()->CreateBasicBlock();
3919 HCompareWithConstant* compare = new(zone()) HCompareWithConstant(
3920 elements_kind_instr,
3921 elements_kind,
3922 Token::EQ);
3923 AddInstruction(compare);
3924 HTest* branch = new(zone()) HTest(compare, if_true, if_false);
3925 current_block()->Finish(branch);
3926
3927 set_current_block(if_true);
3928 HInstruction* access;
3929 if (elements_kind == JSObject::FAST_ELEMENTS) {
3930 HBasicBlock* if_jsarray = graph()->CreateBasicBlock();
3931 HBasicBlock* if_fastobject = graph()->CreateBasicBlock();
3932 HInstruction* typecheck =
3933 AddInstruction(new(zone()) HHasInstanceType(object, JS_ARRAY_TYPE));
3934 HTest* test = new(zone()) HTest(typecheck, if_jsarray, if_fastobject);
3935 current_block()->Finish(test);
3936
3937 set_current_block(if_jsarray);
3938 HInstruction* length = new(zone()) HJSArrayLength(object);
3939 AddInstruction(length);
3940 length->ClearFlag(HValue::kUseGVN);
3941 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
3942 elements = AddInstruction(new(zone()) HLoadElements(object));
3943 elements->ClearFlag(HValue::kUseGVN);
3944 if (is_store) {
3945 access = AddInstruction(
3946 new(zone()) HStoreKeyedFastElement(elements, checked_key, val));
3947 } else {
3948 access = AddInstruction(
3949 new(zone()) HLoadKeyedFastElement(elements, checked_key));
3950 Push(access);
3951 }
3952 *has_side_effects |= access->HasSideEffects();
3953 if (position != -1) {
3954 access->set_position(position);
3955 }
3956 if_jsarray->Goto(join);
3957
3958 set_current_block(if_fastobject);
3959 elements = AddInstruction(new(zone()) HLoadElements(object));
3960 elements->ClearFlag(HValue::kUseGVN);
3961 length = AddInstruction(new(zone()) HFixedArrayLength(elements));
3962 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
3963 if (is_store) {
3964 access = AddInstruction(
3965 new(zone()) HStoreKeyedFastElement(elements, checked_key, val));
3966 } else {
3967 access = AddInstruction(
3968 new(zone()) HLoadKeyedFastElement(elements, checked_key));
3969 }
3970 } else {
fschneider 2011/06/16 13:21:28 Do you handle FAST_DOUBLE_ELEMENTS at all? For now
Jakob Kummerow 2011/06/17 08:06:09 Uhm... no, I don't handle them, because Hydrogen h
3971 if (is_store) {
3972 ASSERT(val != NULL);
3973 switch (elements_kind) {
fschneider 2011/06/16 13:21:28 Could you have a helper inserting the conversion i
Jakob Kummerow 2011/06/17 08:06:09 Good idea. Done.
3974 case JSObject::EXTERNAL_PIXEL_ELEMENTS: {
3975 HClampToUint8* clamp = new(zone()) HClampToUint8(val);
3976 AddInstruction(clamp);
3977 val = clamp;
3978 break;
3979 }
3980 case JSObject::EXTERNAL_BYTE_ELEMENTS:
3981 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3982 case JSObject::EXTERNAL_SHORT_ELEMENTS:
3983 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3984 case JSObject::EXTERNAL_INT_ELEMENTS:
3985 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: {
3986 HToInt32* floor_val = new(zone()) HToInt32(val);
3987 AddInstruction(floor_val);
3988 val = floor_val;
3989 break;
3990 }
3991 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
3992 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
3993 break;
3994 case JSObject::FAST_ELEMENTS:
3995 case JSObject::FAST_DOUBLE_ELEMENTS:
3996 case JSObject::DICTIONARY_ELEMENTS:
3997 UNREACHABLE();
3998 break;
3999 }
4000 access = AddInstruction(
4001 new(zone()) HStoreKeyedSpecializedArrayElement(
4002 external_elements, checked_key, val, elements_kind));
4003 } else {
4004 access = AddInstruction(
4005 new(zone()) HLoadKeyedSpecializedArrayElement(
4006 external_elements, checked_key, elements_kind));
4007 }
4008 }
4009 *has_side_effects |= access->HasSideEffects();
fschneider 2011/06/16 13:21:28 Isn't it always the case that (*has_side_effects =
Jakob Kummerow 2011/06/17 08:06:09 That assumption does indeed seem to be true in all
4010 if (position != -1) {
4011 access->set_position(position);
4012 }
4013 if (!is_store) {
4014 Push(access);
4015 }
4016 current_block()->Goto(join);
4017 set_current_block(if_false);
4018 }
4019 }
4020
4021 // Deopt if none of the cases matched.
4022 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses);
4023 join->SetJoinId(ast_id);
4024 set_current_block(join);
4025 if (!is_store) {
fschneider 2011/06/16 13:21:28 Maybe shorten this to: return is_store ? NULL : P
Jakob Kummerow 2011/06/17 08:06:09 Done.
4026 return Pop();
4027 }
4028 return NULL;
4029 }
4030
4031
4032 HValue* HGraphBuilder::HandleKeyedElementAccess(HValue* obj,
4033 HValue* key,
4034 HValue* val,
4035 Expression* expr,
4036 int ast_id,
4037 int position,
4038 bool is_store,
4039 bool* has_side_effects) {
4040 ASSERT(!expr->IsPropertyName());
4041 HInstruction* instr = NULL;
4042 if (expr->IsMonomorphic()) {
4043 instr = BuildMonomorphicElementAccess(obj, key, val, expr, is_store);
4044 } else if (expr->GetReceiverTypes() != NULL &&
4045 !expr->GetReceiverTypes()->is_empty()) {
4046 return HandlePolymorphicElementAccess(
4047 obj, key, val, expr, ast_id, position, is_store, has_side_effects);
4048 } else {
4049 if (is_store) {
4050 instr = BuildStoreKeyedGeneric(obj, key, val);
4051 } else {
4052 instr = BuildLoadKeyedGeneric(obj, key);
4053 }
4054 }
4055 if (position != -1) {
fschneider 2011/06/16 13:21:28 Not sure, that you actually need to check for -1 (
Jakob Kummerow 2011/06/17 08:06:09 Done. Since kNoPosition is the default value anywa
4056 instr->set_position(position);
4057 }
4058 AddInstruction(instr);
4059 *has_side_effects = instr->HasSideEffects();
4060 return instr;
3824 } 4061 }
3825 4062
3826 4063
3827 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object, 4064 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object,
3828 HValue* key, 4065 HValue* key,
3829 HValue* value) { 4066 HValue* value) {
3830 HValue* context = environment()->LookupContext(); 4067 HValue* context = environment()->LookupContext();
3831 return new(zone()) HStoreKeyedGeneric( 4068 return new(zone()) HStoreKeyedGeneric(
3832 context, 4069 context,
3833 object, 4070 object,
3834 key, 4071 key,
3835 value, 4072 value,
3836 function_strict_mode()); 4073 function_strict_mode());
3837 } 4074 }
3838 4075
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) { 4076 bool HGraphBuilder::TryArgumentsAccess(Property* expr) {
3945 VariableProxy* proxy = expr->obj()->AsVariableProxy(); 4077 VariableProxy* proxy = expr->obj()->AsVariableProxy();
3946 if (proxy == NULL) return false; 4078 if (proxy == NULL) return false;
3947 if (!proxy->var()->IsStackAllocated()) return false; 4079 if (!proxy->var()->IsStackAllocated()) return false;
3948 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { 4080 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
3949 return false; 4081 return false;
3950 } 4082 }
3951 4083
3952 // Our implementation of arguments (based on this stack frame or an 4084 // Our implementation of arguments (based on this stack frame or an
3953 // adapter below it) does not work for inlined functions. 4085 // 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); 4159 instr = new(zone()) HLoadNamedFieldPolymorphic(obj, types, name);
4028 } else { 4160 } else {
4029 instr = BuildLoadNamedGeneric(obj, expr); 4161 instr = BuildLoadNamedGeneric(obj, expr);
4030 } 4162 }
4031 4163
4032 } else { 4164 } else {
4033 CHECK_ALIVE(VisitForValue(expr->key())); 4165 CHECK_ALIVE(VisitForValue(expr->key()));
4034 4166
4035 HValue* key = Pop(); 4167 HValue* key = Pop();
4036 HValue* obj = Pop(); 4168 HValue* obj = Pop();
4037 instr = BuildLoadKeyed(obj, key, expr); 4169
4170 bool has_side_effects = false;
4171 HValue* load = HandleKeyedElementAccess(
4172 obj, key, NULL, expr, expr->id(), expr->position(),
4173 false, // is_store,
fschneider 2011/06/16 13:21:28 This comment looks like commented out code. Maybe
Jakob Kummerow 2011/06/17 08:06:09 I see your point. I've removed the comma. Is that
4174 &has_side_effects);
4175 if (has_side_effects) {
4176 if (ast_context()->IsEffect()) {
4177 AddSimulate(expr->id());
4178 } else {
4179 Push(load);
4180 AddSimulate(expr->id());
4181 Drop(1);
4182 }
4183 }
4184 ast_context()->ReturnValue(load);
4185 return;
4038 } 4186 }
4039 instr->set_position(expr->position()); 4187 instr->set_position(expr->position());
4040 ast_context()->ReturnInstruction(instr, expr->id()); 4188 ast_context()->ReturnInstruction(instr, expr->id());
4041 } 4189 }
4042 4190
4043 4191
4044 void HGraphBuilder::AddCheckConstantFunction(Call* expr, 4192 void HGraphBuilder::AddCheckConstantFunction(Call* expr,
4045 HValue* receiver, 4193 HValue* receiver,
4046 Handle<Map> receiver_map, 4194 Handle<Map> receiver_map,
4047 bool smi_and_map_check) { 4195 bool smi_and_map_check) {
(...skipping 989 matching lines...) Expand 10 before | Expand all | Expand 10 after
5037 5185
5038 } else { 5186 } else {
5039 // Keyed property. 5187 // Keyed property.
5040 if (returns_original_input) Push(graph_->GetConstantUndefined()); 5188 if (returns_original_input) Push(graph_->GetConstantUndefined());
5041 5189
5042 CHECK_ALIVE(VisitForValue(prop->obj())); 5190 CHECK_ALIVE(VisitForValue(prop->obj()));
5043 CHECK_ALIVE(VisitForValue(prop->key())); 5191 CHECK_ALIVE(VisitForValue(prop->key()));
5044 HValue* obj = environment()->ExpressionStackAt(1); 5192 HValue* obj = environment()->ExpressionStackAt(1);
5045 HValue* key = environment()->ExpressionStackAt(0); 5193 HValue* key = environment()->ExpressionStackAt(0);
5046 5194
5047 HInstruction* load = BuildLoadKeyed(obj, key, prop); 5195 bool has_side_effects = false;
5048 PushAndAdd(load); 5196 HValue* load = HandleKeyedElementAccess(
5049 if (load->HasSideEffects()) AddSimulate(expr->CountId()); 5197 obj, key, NULL, prop, expr->CountId(), -1,
5198 false, // is_store
5199 &has_side_effects);
5200 Push(load);
5201 if (has_side_effects) AddSimulate(expr->CountId());
5050 5202
5051 after = BuildIncrement(returns_original_input, expr); 5203 after = BuildIncrement(returns_original_input, expr);
5052 input = Pop(); 5204 input = Pop();
5053 5205
5054 expr->RecordTypeFeedback(oracle()); 5206 expr->RecordTypeFeedback(oracle());
5055 HInstruction* store = BuildStoreKeyed(obj, key, after, expr); 5207 HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(), -1,
5056 AddInstruction(store); 5208 true, // is_store
5209 &has_side_effects);
fschneider 2011/06/16 13:21:28 Stores will always have a side effect.
Jakob Kummerow 2011/06/17 08:06:09 Done.
5057 5210
5058 // Drop the key from the bailout environment. Overwrite the receiver 5211 // Drop the key from the bailout environment. Overwrite the receiver
5059 // with the result of the operation, and the placeholder with the 5212 // with the result of the operation, and the placeholder with the
5060 // original value if necessary. 5213 // original value if necessary.
5061 Drop(1); 5214 Drop(1);
5062 environment()->SetExpressionStackAt(0, after); 5215 environment()->SetExpressionStackAt(0, after);
5063 if (returns_original_input) environment()->SetExpressionStackAt(1, input); 5216 if (returns_original_input) environment()->SetExpressionStackAt(1, input);
5064 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); 5217 if (has_side_effects) AddSimulate(expr->AssignmentId());
5065 } 5218 }
5066 } 5219 }
5067 5220
5068 Drop(returns_original_input ? 2 : 1); 5221 Drop(returns_original_input ? 2 : 1);
5069 ast_context()->ReturnValue(expr->is_postfix() ? input : after); 5222 ast_context()->ReturnValue(expr->is_postfix() ? input : after);
5070 } 5223 }
5071 5224
5072 5225
5073 HCompareSymbolEq* HGraphBuilder::BuildSymbolCompare(HValue* left, 5226 HCompareSymbolEq* HGraphBuilder::BuildSymbolCompare(HValue* left,
5074 HValue* right, 5227 HValue* right,
(...skipping 1332 matching lines...) Expand 10 before | Expand all | Expand 10 after
6407 } 6560 }
6408 } 6561 }
6409 6562
6410 #ifdef DEBUG 6563 #ifdef DEBUG
6411 if (graph_ != NULL) graph_->Verify(); 6564 if (graph_ != NULL) graph_->Verify();
6412 if (allocator_ != NULL) allocator_->Verify(); 6565 if (allocator_ != NULL) allocator_->Verify();
6413 #endif 6566 #endif
6414 } 6567 }
6415 6568
6416 } } // namespace v8::internal 6569 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698