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

Side by Side Diff: src/x64/lithium-codegen-x64.cc

Issue 8256016: Eliminate write barrier for global stores at compile time if value stored is a smi. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 2 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/x64/lithium-codegen-x64.h ('k') | src/x64/lithium-x64.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 2037 matching lines...) Expand 10 before | Expand all | Expand 10 after
2048 // to update the property details in the property dictionary to mark 2048 // to update the property details in the property dictionary to mark
2049 // it as no longer deleted. We deoptimize in that case. 2049 // it as no longer deleted. We deoptimize in that case.
2050 if (instr->hydrogen()->RequiresHoleCheck()) { 2050 if (instr->hydrogen()->RequiresHoleCheck()) {
2051 __ CompareRoot(Operand(address, 0), Heap::kTheHoleValueRootIndex); 2051 __ CompareRoot(Operand(address, 0), Heap::kTheHoleValueRootIndex);
2052 DeoptimizeIf(equal, instr->environment()); 2052 DeoptimizeIf(equal, instr->environment());
2053 } 2053 }
2054 2054
2055 // Store the value. 2055 // Store the value.
2056 __ movq(Operand(address, 0), value); 2056 __ movq(Operand(address, 0), value);
2057 2057
2058 Label smi_store; 2058 if (instr->hydrogen()->NeedsWriteBarrier()) {
2059 __ JumpIfSmi(value, &smi_store, Label::kNear); 2059 Label smi_store;
2060 HType type = instr->hydrogen()->value()->type();
2061 if (!type.IsHeapNumber() && !type.IsString() && !type.IsNonPrimitive()) {
2062 __ JumpIfSmi(value, &smi_store, Label::kNear);
2063 }
2060 2064
2061 int offset = JSGlobalPropertyCell::kValueOffset - kHeapObjectTag; 2065 int offset = JSGlobalPropertyCell::kValueOffset - kHeapObjectTag;
2062 __ lea(object, Operand(address, -offset)); 2066 __ lea(object, Operand(address, -offset));
2063 // Cells are always in the remembered set. 2067 // Cells are always in the remembered set.
2064 __ RecordWrite(object, 2068 __ RecordWrite(object,
2065 address, 2069 address,
2066 value, 2070 value,
2067 kSaveFPRegs, 2071 kSaveFPRegs,
2068 OMIT_REMEMBERED_SET, 2072 OMIT_REMEMBERED_SET,
2069 OMIT_SMI_CHECK); 2073 OMIT_SMI_CHECK);
2070 __ bind(&smi_store); 2074 __ bind(&smi_store);
2075 }
2071 } 2076 }
2072 2077
2073 2078
2074 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { 2079 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
2075 ASSERT(ToRegister(instr->global_object()).is(rdx)); 2080 ASSERT(ToRegister(instr->global_object()).is(rdx));
2076 ASSERT(ToRegister(instr->value()).is(rax)); 2081 ASSERT(ToRegister(instr->value()).is(rax));
2077 2082
2078 __ Move(rcx, instr->name()); 2083 __ Move(rcx, instr->name());
2079 Handle<Code> ic = instr->strict_mode() 2084 Handle<Code> ic = instr->strict_mode()
2080 ? isolate()->builtins()->StoreIC_Initialize_Strict() 2085 ? isolate()->builtins()->StoreIC_Initialize_Strict()
2081 : isolate()->builtins()->StoreIC_Initialize(); 2086 : isolate()->builtins()->StoreIC_Initialize();
2082 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); 2087 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr);
2083 } 2088 }
2084 2089
2085 2090
2086 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { 2091 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
2087 Register context = ToRegister(instr->context()); 2092 Register context = ToRegister(instr->context());
2088 Register result = ToRegister(instr->result()); 2093 Register result = ToRegister(instr->result());
2089 __ movq(result, ContextOperand(context, instr->slot_index())); 2094 __ movq(result, ContextOperand(context, instr->slot_index()));
2090 } 2095 }
2091 2096
2092 2097
2093 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { 2098 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
2094 Register context = ToRegister(instr->context()); 2099 Register context = ToRegister(instr->context());
2095 Register value = ToRegister(instr->value()); 2100 Register value = ToRegister(instr->value());
2096 __ movq(ContextOperand(context, instr->slot_index()), value); 2101 __ movq(ContextOperand(context, instr->slot_index()), value);
2097 if (instr->needs_write_barrier()) { 2102 if (instr->hydrogen()->NeedsWriteBarrier()) {
2103 HType type = instr->hydrogen()->value()->type();
2104 SmiCheck check_needed =
2105 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
2098 int offset = Context::SlotOffset(instr->slot_index()); 2106 int offset = Context::SlotOffset(instr->slot_index());
2099 Register scratch = ToRegister(instr->TempAt(0)); 2107 Register scratch = ToRegister(instr->TempAt(0));
2100 __ RecordWriteContextSlot(context, offset, value, scratch, kSaveFPRegs); 2108 __ RecordWriteContextSlot(context,
2109 offset,
2110 value,
2111 scratch,
2112 kSaveFPRegs,
2113 EMIT_REMEMBERED_SET,
2114 check_needed);
2101 } 2115 }
2102 } 2116 }
2103 2117
2104 2118
2105 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { 2119 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
2106 Register object = ToRegister(instr->InputAt(0)); 2120 Register object = ToRegister(instr->InputAt(0));
2107 Register result = ToRegister(instr->result()); 2121 Register result = ToRegister(instr->result());
2108 if (instr->hydrogen()->is_in_object()) { 2122 if (instr->hydrogen()->is_in_object()) {
2109 __ movq(result, FieldOperand(object, instr->hydrogen()->offset())); 2123 __ movq(result, FieldOperand(object, instr->hydrogen()->offset()));
2110 } else { 2124 } else {
(...skipping 943 matching lines...) Expand 10 before | Expand all | Expand 10 after
3054 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { 3068 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
3055 Register object = ToRegister(instr->object()); 3069 Register object = ToRegister(instr->object());
3056 Register value = ToRegister(instr->value()); 3070 Register value = ToRegister(instr->value());
3057 int offset = instr->offset(); 3071 int offset = instr->offset();
3058 3072
3059 if (!instr->transition().is_null()) { 3073 if (!instr->transition().is_null()) {
3060 __ Move(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); 3074 __ Move(FieldOperand(object, HeapObject::kMapOffset), instr->transition());
3061 } 3075 }
3062 3076
3063 // Do the store. 3077 // Do the store.
3078 HType type = instr->hydrogen()->value()->type();
3079 SmiCheck check_needed =
3080 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
3064 if (instr->is_in_object()) { 3081 if (instr->is_in_object()) {
3065 __ movq(FieldOperand(object, offset), value); 3082 __ movq(FieldOperand(object, offset), value);
3066 if (instr->needs_write_barrier()) { 3083 if (instr->hydrogen()->NeedsWriteBarrier()) {
3067 Register temp = ToRegister(instr->TempAt(0)); 3084 Register temp = ToRegister(instr->TempAt(0));
3068 // Update the write barrier for the object for in-object properties. 3085 // Update the write barrier for the object for in-object properties.
3069 __ RecordWriteField(object, offset, value, temp, kSaveFPRegs); 3086 __ RecordWriteField(object,
3087 offset,
3088 value,
3089 temp,
3090 kSaveFPRegs,
3091 EMIT_REMEMBERED_SET,
3092 check_needed);
3070 } 3093 }
3071 } else { 3094 } else {
3072 Register temp = ToRegister(instr->TempAt(0)); 3095 Register temp = ToRegister(instr->TempAt(0));
3073 __ movq(temp, FieldOperand(object, JSObject::kPropertiesOffset)); 3096 __ movq(temp, FieldOperand(object, JSObject::kPropertiesOffset));
3074 __ movq(FieldOperand(temp, offset), value); 3097 __ movq(FieldOperand(temp, offset), value);
3075 if (instr->needs_write_barrier()) { 3098 if (instr->hydrogen()->NeedsWriteBarrier()) {
3076 // Update the write barrier for the properties array. 3099 // Update the write barrier for the properties array.
3077 // object is used as a scratch register. 3100 // object is used as a scratch register.
3078 __ RecordWriteField(temp, offset, value, object, kSaveFPRegs); 3101 __ RecordWriteField(temp,
3102 offset,
3103 value,
3104 object,
3105 kSaveFPRegs,
3106 EMIT_REMEMBERED_SET,
3107 check_needed);
3079 } 3108 }
3080 } 3109 }
3081 } 3110 }
3082 3111
3083 3112
3084 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { 3113 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
3085 ASSERT(ToRegister(instr->object()).is(rdx)); 3114 ASSERT(ToRegister(instr->object()).is(rdx));
3086 ASSERT(ToRegister(instr->value()).is(rax)); 3115 ASSERT(ToRegister(instr->value()).is(rax));
3087 3116
3088 __ Move(rcx, instr->hydrogen()->name()); 3117 __ Move(rcx, instr->hydrogen()->name());
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
3175 __ movq(FieldOperand(elements, offset), value); 3204 __ movq(FieldOperand(elements, offset), value);
3176 } else { 3205 } else {
3177 __ movq(FieldOperand(elements, 3206 __ movq(FieldOperand(elements,
3178 key, 3207 key,
3179 times_pointer_size, 3208 times_pointer_size,
3180 FixedArray::kHeaderSize), 3209 FixedArray::kHeaderSize),
3181 value); 3210 value);
3182 } 3211 }
3183 3212
3184 if (instr->hydrogen()->NeedsWriteBarrier()) { 3213 if (instr->hydrogen()->NeedsWriteBarrier()) {
3214 HType type = instr->hydrogen()->value()->type();
3215 SmiCheck check_needed =
3216 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
3185 // Compute address of modified element and store it into key register. 3217 // Compute address of modified element and store it into key register.
3186 __ lea(key, FieldOperand(elements, 3218 __ lea(key, FieldOperand(elements,
3187 key, 3219 key,
3188 times_pointer_size, 3220 times_pointer_size,
3189 FixedArray::kHeaderSize)); 3221 FixedArray::kHeaderSize));
3190 __ RecordWrite(elements, key, value, kSaveFPRegs); 3222 __ RecordWrite(elements,
3223 key,
3224 value,
3225 kSaveFPRegs,
3226 EMIT_REMEMBERED_SET,
3227 check_needed);
3191 } 3228 }
3192 } 3229 }
3193 3230
3194 3231
3195 void LCodeGen::DoStoreKeyedFastDoubleElement( 3232 void LCodeGen::DoStoreKeyedFastDoubleElement(
3196 LStoreKeyedFastDoubleElement* instr) { 3233 LStoreKeyedFastDoubleElement* instr) {
3197 XMMRegister value = ToDoubleRegister(instr->value()); 3234 XMMRegister value = ToDoubleRegister(instr->value());
3198 Label have_value; 3235 Label have_value;
3199 3236
3200 __ ucomisd(value, value); 3237 __ ucomisd(value, value);
(...skipping 767 matching lines...) Expand 10 before | Expand all | Expand 10 after
3968 } 4005 }
3969 4006
3970 4007
3971 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { 4008 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
3972 Register input = ToRegister(instr->InputAt(0)); 4009 Register input = ToRegister(instr->InputAt(0));
3973 int true_block = chunk_->LookupDestination(instr->true_block_id()); 4010 int true_block = chunk_->LookupDestination(instr->true_block_id());
3974 int false_block = chunk_->LookupDestination(instr->false_block_id()); 4011 int false_block = chunk_->LookupDestination(instr->false_block_id());
3975 Label* true_label = chunk_->GetAssemblyLabel(true_block); 4012 Label* true_label = chunk_->GetAssemblyLabel(true_block);
3976 Label* false_label = chunk_->GetAssemblyLabel(false_block); 4013 Label* false_label = chunk_->GetAssemblyLabel(false_block);
3977 4014
3978 Condition final_branch_condition = EmitTypeofIs(true_label, 4015 Condition final_branch_condition =
3979 false_label, 4016 EmitTypeofIs(true_label, false_label, input, instr->type_literal());
3980 input, 4017 if (final_branch_condition != no_condition) {
3981 instr->type_literal()); 4018 EmitBranch(true_block, false_block, final_branch_condition);
3982 4019 }
3983 EmitBranch(true_block, false_block, final_branch_condition);
3984 } 4020 }
3985 4021
3986 4022
3987 Condition LCodeGen::EmitTypeofIs(Label* true_label, 4023 Condition LCodeGen::EmitTypeofIs(Label* true_label,
3988 Label* false_label, 4024 Label* false_label,
3989 Register input, 4025 Register input,
3990 Handle<String> type_name) { 4026 Handle<String> type_name) {
3991 Condition final_branch_condition = no_condition; 4027 Condition final_branch_condition = no_condition;
3992 if (type_name->Equals(heap()->number_symbol())) { 4028 if (type_name->Equals(heap()->number_symbol())) {
3993 __ JumpIfSmi(input, true_label); 4029 __ JumpIfSmi(input, true_label);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
4041 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); 4077 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input);
4042 __ j(below, false_label); 4078 __ j(below, false_label);
4043 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); 4079 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
4044 __ j(above, false_label); 4080 __ j(above, false_label);
4045 // Check for undetectable objects => false. 4081 // Check for undetectable objects => false.
4046 __ testb(FieldOperand(input, Map::kBitFieldOffset), 4082 __ testb(FieldOperand(input, Map::kBitFieldOffset),
4047 Immediate(1 << Map::kIsUndetectable)); 4083 Immediate(1 << Map::kIsUndetectable));
4048 final_branch_condition = zero; 4084 final_branch_condition = zero;
4049 4085
4050 } else { 4086 } else {
4051 final_branch_condition = never;
4052 __ jmp(false_label); 4087 __ jmp(false_label);
4053 } 4088 }
4054 4089
4055 return final_branch_condition; 4090 return final_branch_condition;
4056 } 4091 }
4057 4092
4058 4093
4059 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { 4094 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
4060 Register temp = ToRegister(instr->TempAt(0)); 4095 Register temp = ToRegister(instr->TempAt(0));
4061 int true_block = chunk_->LookupDestination(instr->true_block_id()); 4096 int true_block = chunk_->LookupDestination(instr->true_block_id());
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
4196 RegisterEnvironmentForDeoptimization(environment); 4231 RegisterEnvironmentForDeoptimization(environment);
4197 ASSERT(osr_pc_offset_ == -1); 4232 ASSERT(osr_pc_offset_ == -1);
4198 osr_pc_offset_ = masm()->pc_offset(); 4233 osr_pc_offset_ = masm()->pc_offset();
4199 } 4234 }
4200 4235
4201 #undef __ 4236 #undef __
4202 4237
4203 } } // namespace v8::internal 4238 } } // namespace v8::internal
4204 4239
4205 #endif // V8_TARGET_ARCH_X64 4240 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | src/x64/lithium-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698