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

Side by Side Diff: src/arm/stub-cache-arm.cc

Issue 9310117: Implement KeyedStoreICs to grow arrays on out-of-bound stores. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: nits Created 8 years, 10 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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 3036 matching lines...) Expand 10 before | Expand all | Expand 10 after
3047 // ----------- S t a t e ------------- 3047 // ----------- S t a t e -------------
3048 // -- r0 : value 3048 // -- r0 : value
3049 // -- r1 : key 3049 // -- r1 : key
3050 // -- r2 : receiver 3050 // -- r2 : receiver
3051 // -- lr : return address 3051 // -- lr : return address
3052 // -- r3 : scratch 3052 // -- r3 : scratch
3053 // ----------------------------------- 3053 // -----------------------------------
3054 ElementsKind elements_kind = receiver_map->elements_kind(); 3054 ElementsKind elements_kind = receiver_map->elements_kind();
3055 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; 3055 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
3056 Handle<Code> stub = 3056 Handle<Code> stub =
3057 KeyedStoreElementStub(is_js_array, elements_kind).GetCode(); 3057 KeyedStoreElementStub(is_js_array, elements_kind, grow_mode_).GetCode();
3058 3058
3059 __ DispatchMap(r2, r3, receiver_map, stub, DO_SMI_CHECK); 3059 __ DispatchMap(r2, r3, receiver_map, stub, DO_SMI_CHECK);
3060 3060
3061 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 3061 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
3062 __ Jump(ic, RelocInfo::CODE_TARGET); 3062 __ Jump(ic, RelocInfo::CODE_TARGET);
3063 3063
3064 // Return the generated code. 3064 // Return the generated code.
3065 return GetCode(NORMAL, factory()->empty_string()); 3065 return GetCode(NORMAL, factory()->empty_string());
3066 } 3066 }
3067 3067
(...skipping 1024 matching lines...) Expand 10 before | Expand all | Expand 10 after
4092 __ bind(&miss_force_generic); 4092 __ bind(&miss_force_generic);
4093 Handle<Code> miss_ic = 4093 Handle<Code> miss_ic =
4094 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 4094 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
4095 __ Jump(miss_ic, RelocInfo::CODE_TARGET); 4095 __ Jump(miss_ic, RelocInfo::CODE_TARGET);
4096 } 4096 }
4097 4097
4098 4098
4099 void KeyedStoreStubCompiler::GenerateStoreFastElement( 4099 void KeyedStoreStubCompiler::GenerateStoreFastElement(
4100 MacroAssembler* masm, 4100 MacroAssembler* masm,
4101 bool is_js_array, 4101 bool is_js_array,
4102 ElementsKind elements_kind) { 4102 ElementsKind elements_kind,
4103 KeyedAccessGrowMode grow_mode) {
4103 // ----------- S t a t e ------------- 4104 // ----------- S t a t e -------------
4104 // -- r0 : value 4105 // -- r0 : value
4105 // -- r1 : key 4106 // -- r1 : key
4106 // -- r2 : receiver 4107 // -- r2 : receiver
4107 // -- lr : return address 4108 // -- lr : return address
4108 // -- r3 : scratch 4109 // -- r3 : scratch
4109 // -- r4 : scratch (elements) 4110 // -- r4 : scratch (elements)
4110 // ----------------------------------- 4111 // -----------------------------------
4111 Label miss_force_generic, transition_elements_kind; 4112 Label miss_force_generic, transition_elements_kind, grow, slow;
4113 Label finish_store, check_capacity;
4112 4114
4113 Register value_reg = r0; 4115 Register value_reg = r0;
4114 Register key_reg = r1; 4116 Register key_reg = r1;
4115 Register receiver_reg = r2; 4117 Register receiver_reg = r2;
4116 Register scratch = r3; 4118 Register scratch = r4;
4117 Register elements_reg = r4; 4119 Register elements_reg = r3;
4120 Register length_reg = r5;
4121 Register scratch2 = r6;
4118 4122
4119 // This stub is meant to be tail-jumped to, the receiver must already 4123 // This stub is meant to be tail-jumped to, the receiver must already
4120 // have been verified by the caller to not be a smi. 4124 // have been verified by the caller to not be a smi.
4121 4125
4122 // Check that the key is a smi. 4126 // Check that the key is a smi.
4123 __ JumpIfNotSmi(key_reg, &miss_force_generic); 4127 __ JumpIfNotSmi(key_reg, &miss_force_generic);
4124 4128
4125 // Get the elements array and make sure it is a fast element array, not 'cow'. 4129 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
4130 __ JumpIfNotSmi(value_reg, &transition_elements_kind);
4131 }
4132
4133 // Check that the key is within bounds.
4126 __ ldr(elements_reg, 4134 __ ldr(elements_reg,
4127 FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 4135 FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
4128 __ CheckMap(elements_reg,
4129 scratch,
4130 Heap::kFixedArrayMapRootIndex,
4131 &miss_force_generic,
4132 DONT_DO_SMI_CHECK);
4133
4134 // Check that the key is within bounds.
4135 if (is_js_array) { 4136 if (is_js_array) {
4136 __ ldr(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 4137 __ ldr(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
4137 } else { 4138 } else {
4138 __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); 4139 __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
4139 } 4140 }
4140 // Compare smis. 4141 // Compare smis.
4141 __ cmp(key_reg, scratch); 4142 __ cmp(key_reg, scratch);
4142 __ b(hs, &miss_force_generic); 4143 if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
4144 __ b(hs, &grow);
4145 } else {
4146 __ b(hs, &miss_force_generic);
4147 }
4143 4148
4149 // Make sure elements is a fast element array, not 'cow'.
4150 __ CheckMap(elements_reg,
4151 scratch,
4152 Heap::kFixedArrayMapRootIndex,
4153 &miss_force_generic,
4154 DONT_DO_SMI_CHECK);
4155
4156 __ bind(&finish_store);
4144 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { 4157 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
4145 __ JumpIfNotSmi(value_reg, &transition_elements_kind);
4146 __ add(scratch, 4158 __ add(scratch,
4147 elements_reg, 4159 elements_reg,
4148 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 4160 Operand(FixedArray::kHeaderSize - kHeapObjectTag));
4149 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); 4161 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
4150 __ add(scratch, 4162 __ add(scratch,
4151 scratch, 4163 scratch,
4152 Operand(key_reg, LSL, kPointerSizeLog2 - kSmiTagSize)); 4164 Operand(key_reg, LSL, kPointerSizeLog2 - kSmiTagSize));
4153 __ str(value_reg, MemOperand(scratch)); 4165 __ str(value_reg, MemOperand(scratch));
4154 } else { 4166 } else {
4155 ASSERT(elements_kind == FAST_ELEMENTS); 4167 ASSERT(elements_kind == FAST_ELEMENTS);
(...skipping 17 matching lines...) Expand all
4173 __ Ret(); 4185 __ Ret();
4174 4186
4175 __ bind(&miss_force_generic); 4187 __ bind(&miss_force_generic);
4176 Handle<Code> ic = 4188 Handle<Code> ic =
4177 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 4189 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
4178 __ Jump(ic, RelocInfo::CODE_TARGET); 4190 __ Jump(ic, RelocInfo::CODE_TARGET);
4179 4191
4180 __ bind(&transition_elements_kind); 4192 __ bind(&transition_elements_kind);
4181 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 4193 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
4182 __ Jump(ic_miss, RelocInfo::CODE_TARGET); 4194 __ Jump(ic_miss, RelocInfo::CODE_TARGET);
4195
4196 if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
4197 // Grow the array by a single element if possible.
4198 __ bind(&grow);
4199
4200 // Make sure the array is only growing by a single element, anything else
4201 // must be handled by the runtime. Flags already set by previous compare.
4202 __ b(ne, &miss_force_generic);
4203
4204 // Check for the empty array, and preallocate a small backing store if
4205 // possible.
4206 __ ldr(length_reg,
4207 FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
4208 __ ldr(elements_reg,
4209 FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
4210 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex);
Vyacheslav Egorov (Chromium) 2012/02/10 00:19:18 CompareRoot? also root index is incorrect. shoul
danno 2012/02/10 12:25:34 Done.
4211 __ cmp(elements_reg, scratch);
4212 __ b(ne, &check_capacity);
4213
4214 int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements);
4215 __ AllocateInNewSpace(size,
4216 elements_reg,
4217 scratch,
4218 scratch2,
4219 &slow,
4220 TAG_OBJECT);
4221
4222 __ LoadRoot(scratch, Heap::kFixedArrayMapRootIndex);
4223 __ str(scratch, FieldMemOperand(elements_reg, JSObject::kMapOffset));
4224 __ mov(scratch, Operand(Smi::FromInt(JSArray::kPreallocatedArrayElements)));
4225 __ str(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
4226 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
4227 for (int i = 1; i < JSArray::kPreallocatedArrayElements; ++i) {
4228 __ str(scratch, FieldMemOperand(elements_reg, FixedArray::SizeFor(i)));
4229 }
4230
4231 // Store the element at index zero.
4232 __ str(value_reg, FieldMemOperand(elements_reg, FixedArray::SizeFor(0)));
4233
4234 // Install the new backing store in the JSArray.
4235 __ str(elements_reg,
4236 FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
4237 __ RecordWriteField(receiver_reg, JSObject::kElementsOffset, elements_reg,
4238 scratch, kLRHasNotBeenSaved, kDontSaveFPRegs,
4239 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
4240
4241 // Increment the length of the array.
4242 __ add(length_reg, length_reg, Operand(Smi::FromInt(1)));
Vyacheslav Egorov (Chromium) 2012/02/10 00:19:18 can write directly 1 into the length field.
danno 2012/02/10 12:25:34 Done.
4243 __ str(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
4244 __ Ret();
4245
4246 __ bind(&check_capacity);
4247 __ CheckMap(elements_reg,
4248 scratch,
4249 Heap::kFixedArrayMapRootIndex,
4250 &miss_force_generic,
4251 DONT_DO_SMI_CHECK);
4252
4253 __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
4254 __ cmp(length_reg, scratch);
4255 __ b(hs, &slow);
4256
4257 // Grow the array and finish the store.
4258 __ add(length_reg, length_reg, Operand(Smi::FromInt(1)));
4259 __ str(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
4260 __ jmp(&finish_store);
4261
4262 __ bind(&slow);
4263 Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
4264 __ Jump(ic_slow, RelocInfo::CODE_TARGET);
4265 }
4183 } 4266 }
4184 4267
4185 4268
4186 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( 4269 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
4187 MacroAssembler* masm, 4270 MacroAssembler* masm,
4188 bool is_js_array) { 4271 bool is_js_array,
4272 KeyedAccessGrowMode grow_mode) {
4189 // ----------- S t a t e ------------- 4273 // ----------- S t a t e -------------
4190 // -- r0 : value 4274 // -- r0 : value
4191 // -- r1 : key 4275 // -- r1 : key
4192 // -- r2 : receiver 4276 // -- r2 : receiver
4193 // -- lr : return address 4277 // -- lr : return address
4194 // -- r3 : scratch 4278 // -- r3 : scratch
4195 // -- r4 : scratch 4279 // -- r4 : scratch
4196 // -- r5 : scratch 4280 // -- r5 : scratch
4197 // ----------------------------------- 4281 // -----------------------------------
4198 Label miss_force_generic, transition_elements_kind; 4282 Label miss_force_generic, transition_elements_kind, grow, slow;
4283 Label finish_store, check_capacity;
4199 4284
4200 Register value_reg = r0; 4285 Register value_reg = r0;
4201 Register key_reg = r1; 4286 Register key_reg = r1;
4202 Register receiver_reg = r2; 4287 Register receiver_reg = r2;
4203 Register elements_reg = r3; 4288 Register elements_reg = r3;
4204 Register scratch1 = r4; 4289 Register scratch1 = r4;
4205 Register scratch2 = r5; 4290 Register scratch2 = r5;
4206 Register scratch3 = r6; 4291 Register scratch3 = r6;
4207 Register scratch4 = r7; 4292 Register scratch4 = r7;
4293 Register length_reg = r7;
4208 4294
4209 // This stub is meant to be tail-jumped to, the receiver must already 4295 // This stub is meant to be tail-jumped to, the receiver must already
4210 // have been verified by the caller to not be a smi. 4296 // have been verified by the caller to not be a smi.
4211 __ JumpIfNotSmi(key_reg, &miss_force_generic); 4297 __ JumpIfNotSmi(key_reg, &miss_force_generic);
4212 4298
4213 __ ldr(elements_reg, 4299 __ ldr(elements_reg,
4214 FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 4300 FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
4215 4301
4216 // Check that the key is within bounds. 4302 // Check that the key is within bounds.
4217 if (is_js_array) { 4303 if (is_js_array) {
4218 __ ldr(scratch1, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 4304 __ ldr(scratch1, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
4219 } else { 4305 } else {
4220 __ ldr(scratch1, 4306 __ ldr(scratch1,
4221 FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); 4307 FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
4222 } 4308 }
4223 // Compare smis, unsigned compare catches both negative and out-of-bound 4309 // Compare smis, unsigned compare catches both negative and out-of-bound
4224 // indexes. 4310 // indexes.
4225 __ cmp(key_reg, scratch1); 4311 __ cmp(key_reg, scratch1);
4226 __ b(hs, &miss_force_generic); 4312 if (grow_mode == ALLOW_JSARRAY_GROWTH) {
4313 __ b(hs, &grow);
4314 } else {
4315 __ b(hs, &miss_force_generic);
4316 }
4227 4317
4318 __ bind(&finish_store);
4228 __ StoreNumberToDoubleElements(value_reg, 4319 __ StoreNumberToDoubleElements(value_reg,
4229 key_reg, 4320 key_reg,
4230 receiver_reg, 4321 receiver_reg,
4231 elements_reg, 4322 elements_reg,
4232 scratch1, 4323 scratch1,
4233 scratch2, 4324 scratch2,
4234 scratch3, 4325 scratch3,
4235 scratch4, 4326 scratch4,
4236 &transition_elements_kind); 4327 &transition_elements_kind);
4237 __ Ret(); 4328 __ Ret();
4238 4329
4239 // Handle store cache miss, replacing the ic with the generic stub. 4330 // Handle store cache miss, replacing the ic with the generic stub.
4240 __ bind(&miss_force_generic); 4331 __ bind(&miss_force_generic);
4241 Handle<Code> ic = 4332 Handle<Code> ic =
4242 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 4333 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
4243 __ Jump(ic, RelocInfo::CODE_TARGET); 4334 __ Jump(ic, RelocInfo::CODE_TARGET);
4244 4335
4245 __ bind(&transition_elements_kind); 4336 __ bind(&transition_elements_kind);
4246 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 4337 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
4247 __ Jump(ic_miss, RelocInfo::CODE_TARGET); 4338 __ Jump(ic_miss, RelocInfo::CODE_TARGET);
4339
4340 if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
4341 // Grow the array by a single element if possible.
4342 __ bind(&grow);
4343
4344 // Make sure the array is only growing by a single element, anything else
4345 // must be handled by the runtime. Flags already set by previous compare.
4346 __ b(ne, &miss_force_generic);
4347
4348 // Transition on values that can't be stored in a FixedDoubleArray.
4349 Label value_is_smi;
4350 __ JumpIfSmi(value_reg, &value_is_smi);
4351 __ ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
4352 __ LoadRoot(scratch2, Heap::kHeapNumberMapRootIndex);
4353 __ cmp(scratch1, scratch2);
Vyacheslav Egorov (Chromium) 2012/02/10 00:19:18 CompareRoot
danno 2012/02/10 12:25:34 Done.
4354 __ b(ne, &transition_elements_kind);
4355 __ bind(&value_is_smi);
4356
4357 // Check for the empty array, and preallocate a small backing store if
4358 // possible.
4359 __ ldr(length_reg,
4360 FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
4361 __ ldr(elements_reg,
4362 FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
4363 __ LoadRoot(scratch1, Heap::kHeapNumberMapRootIndex);
4364 __ cmp(elements_reg, scratch1);
Vyacheslav Egorov (Chromium) 2012/02/10 00:19:18 CompareRoot also root index is incorrect. should
danno 2012/02/10 12:25:34 Done.
4365 __ b(ne, &check_capacity);
4366
4367 int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements);
4368 __ AllocateInNewSpace(size,
4369 elements_reg,
4370 scratch1,
4371 scratch2,
4372 &slow,
4373 TAG_OBJECT);
4374
4375 // Initialize the new FixedDoubleArray.
4376 __ LoadRoot(scratch1, Heap::kFixedDoubleArrayMapRootIndex);
4377 __ str(scratch1, FieldMemOperand(elements_reg, JSObject::kMapOffset));
4378 __ mov(scratch1,
4379 Operand(Smi::FromInt(JSArray::kPreallocatedArrayElements)));
4380 __ str(scratch1,
4381 FieldMemOperand(elements_reg, FixedDoubleArray::kLengthOffset));
4382
4383 // Install the new backing store in the JSArray.
4384 __ str(elements_reg,
Vyacheslav Egorov (Chromium) 2012/02/10 00:19:18 elements of the backing store are completely unini
danno 2012/02/10 12:25:34 Done.
4385 FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
4386 __ RecordWriteField(receiver_reg, JSObject::kElementsOffset, elements_reg,
4387 scratch1, kLRHasNotBeenSaved, kDontSaveFPRegs,
4388 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
4389
4390 // Increment the length of the array.
4391 __ add(length_reg, length_reg, Operand(Smi::FromInt(1)));
Vyacheslav Egorov (Chromium) 2012/02/10 00:19:18 store 1 directly without addition.
danno 2012/02/10 12:25:34 Done.
4392 __ str(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
4393 __ jmp(&finish_store);
4394
4395 __ bind(&check_capacity);
4396 // Make sure that the backing store can hold additional elements.
4397 __ ldr(scratch1,
4398 FieldMemOperand(elements_reg, FixedDoubleArray::kLengthOffset));
4399 __ cmp(length_reg, scratch1);
4400 __ b(hs, &slow);
4401
4402 // Grow the array and finish the store.
4403 __ add(length_reg, length_reg, Operand(Smi::FromInt(1)));
4404 __ str(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
4405 __ jmp(&finish_store);
4406
4407 __ bind(&slow);
4408 Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
4409 __ Jump(ic_slow, RelocInfo::CODE_TARGET);
4410 }
4248 } 4411 }
4249 4412
4250 4413
4251 #undef __ 4414 #undef __
4252 4415
4253 } } // namespace v8::internal 4416 } } // namespace v8::internal
4254 4417
4255 #endif // V8_TARGET_ARCH_ARM 4418 #endif // V8_TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698