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

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

Issue 9378005: MIPS: Implement KeyedStoreICs to grow arrays on out-of-bound stores. (Closed)
Patch Set: rebased on r10702 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
« no previous file with comments | « src/mips/codegen-mips.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 3040 matching lines...) Expand 10 before | Expand all | Expand 10 after
3051 // ----------- S t a t e ------------- 3051 // ----------- S t a t e -------------
3052 // -- a0 : value 3052 // -- a0 : value
3053 // -- a1 : key 3053 // -- a1 : key
3054 // -- a2 : receiver 3054 // -- a2 : receiver
3055 // -- ra : return address 3055 // -- ra : return address
3056 // -- a3 : scratch 3056 // -- a3 : scratch
3057 // ----------------------------------- 3057 // -----------------------------------
3058 ElementsKind elements_kind = receiver_map->elements_kind(); 3058 ElementsKind elements_kind = receiver_map->elements_kind();
3059 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; 3059 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
3060 Handle<Code> stub = 3060 Handle<Code> stub =
3061 KeyedStoreElementStub(is_js_array, elements_kind).GetCode(); 3061 KeyedStoreElementStub(is_js_array, elements_kind, grow_mode_).GetCode();
3062 3062
3063 __ DispatchMap(a2, a3, receiver_map, stub, DO_SMI_CHECK); 3063 __ DispatchMap(a2, a3, receiver_map, stub, DO_SMI_CHECK);
3064 3064
3065 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 3065 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
3066 __ Jump(ic, RelocInfo::CODE_TARGET); 3066 __ Jump(ic, RelocInfo::CODE_TARGET);
3067 3067
3068 // Return the generated code. 3068 // Return the generated code.
3069 return GetCode(NORMAL, factory()->empty_string()); 3069 return GetCode(NORMAL, factory()->empty_string());
3070 } 3070 }
3071 3071
(...skipping 1089 matching lines...) Expand 10 before | Expand all | Expand 10 after
4161 __ bind(&miss_force_generic); 4161 __ bind(&miss_force_generic);
4162 Handle<Code> miss_ic = 4162 Handle<Code> miss_ic =
4163 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 4163 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
4164 __ Jump(miss_ic, RelocInfo::CODE_TARGET); 4164 __ Jump(miss_ic, RelocInfo::CODE_TARGET);
4165 } 4165 }
4166 4166
4167 4167
4168 void KeyedStoreStubCompiler::GenerateStoreFastElement( 4168 void KeyedStoreStubCompiler::GenerateStoreFastElement(
4169 MacroAssembler* masm, 4169 MacroAssembler* masm,
4170 bool is_js_array, 4170 bool is_js_array,
4171 ElementsKind elements_kind) { 4171 ElementsKind elements_kind,
4172 KeyedAccessGrowMode grow_mode) {
4172 // ----------- S t a t e ------------- 4173 // ----------- S t a t e -------------
4173 // -- a0 : value 4174 // -- a0 : value
4174 // -- a1 : key 4175 // -- a1 : key
4175 // -- a2 : receiver 4176 // -- a2 : receiver
4176 // -- ra : return address 4177 // -- ra : return address
4177 // -- a3 : scratch 4178 // -- a3 : scratch
4178 // -- a4 : scratch (elements) 4179 // -- a4 : scratch (elements)
4179 // ----------------------------------- 4180 // -----------------------------------
4180 Label miss_force_generic, transition_elements_kind; 4181 Label miss_force_generic, transition_elements_kind, grow, slow;
4182 Label finish_store, check_capacity;
4181 4183
4182 Register value_reg = a0; 4184 Register value_reg = a0;
4183 Register key_reg = a1; 4185 Register key_reg = a1;
4184 Register receiver_reg = a2; 4186 Register receiver_reg = a2;
4185 Register scratch = a3; 4187 Register scratch = t0;
4186 Register elements_reg = t0; 4188 Register elements_reg = a3;
4187 Register scratch2 = t1; 4189 Register length_reg = t1;
4188 Register scratch3 = t2; 4190 Register scratch2 = t2;
4191 Register scratch3 = t3;
4189 4192
4190 // This stub is meant to be tail-jumped to, the receiver must already 4193 // This stub is meant to be tail-jumped to, the receiver must already
4191 // have been verified by the caller to not be a smi. 4194 // have been verified by the caller to not be a smi.
4192 4195
4193 // Check that the key is a smi. 4196 // Check that the key is a smi.
4194 __ JumpIfNotSmi(key_reg, &miss_force_generic); 4197 __ JumpIfNotSmi(key_reg, &miss_force_generic);
4195 4198
4196 // Get the elements array and make sure it is a fast element array, not 'cow'. 4199 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
4200 __ JumpIfNotSmi(value_reg, &transition_elements_kind);
4201 }
4202
4203 // Check that the key is within bounds.
4197 __ lw(elements_reg, 4204 __ lw(elements_reg,
4198 FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 4205 FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
4206 if (is_js_array) {
4207 __ lw(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
4208 } else {
4209 __ lw(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
4210 }
4211 // Compare smis.
4212 if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
4213 __ Branch(&grow, hs, key_reg, Operand(scratch));
4214 } else {
4215 __ Branch(&miss_force_generic, hs, key_reg, Operand(scratch));
4216 }
4217
4218 // Make sure elements is a fast element array, not 'cow'.
4199 __ CheckMap(elements_reg, 4219 __ CheckMap(elements_reg,
4200 scratch, 4220 scratch,
4201 Heap::kFixedArrayMapRootIndex, 4221 Heap::kFixedArrayMapRootIndex,
4202 &miss_force_generic, 4222 &miss_force_generic,
4203 DONT_DO_SMI_CHECK); 4223 DONT_DO_SMI_CHECK);
4204 4224
4205 // Check that the key is within bounds. 4225 __ bind(&finish_store);
4206 if (is_js_array) {
4207 __ lw(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
4208 } else {
4209 __ lw(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
4210 }
4211 // Compare smis.
4212 __ Branch(&miss_force_generic, hs, key_reg, Operand(scratch));
4213 4226
4214 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { 4227 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
4215 __ JumpIfNotSmi(value_reg, &transition_elements_kind);
4216 __ Addu(scratch, 4228 __ Addu(scratch,
4217 elements_reg, 4229 elements_reg,
4218 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 4230 Operand(FixedArray::kHeaderSize - kHeapObjectTag));
4219 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); 4231 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
4220 __ sll(scratch2, key_reg, kPointerSizeLog2 - kSmiTagSize); 4232 __ sll(scratch2, key_reg, kPointerSizeLog2 - kSmiTagSize);
4221 __ Addu(scratch, scratch, scratch2); 4233 __ Addu(scratch, scratch, scratch2);
4222 __ sw(value_reg, MemOperand(scratch)); 4234 __ sw(value_reg, MemOperand(scratch));
4223 } else { 4235 } else {
4224 ASSERT(elements_kind == FAST_ELEMENTS); 4236 ASSERT(elements_kind == FAST_ELEMENTS);
4225 __ Addu(scratch, 4237 __ Addu(scratch,
(...skipping 16 matching lines...) Expand all
4242 __ Ret(); 4254 __ Ret();
4243 4255
4244 __ bind(&miss_force_generic); 4256 __ bind(&miss_force_generic);
4245 Handle<Code> ic = 4257 Handle<Code> ic =
4246 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 4258 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
4247 __ Jump(ic, RelocInfo::CODE_TARGET); 4259 __ Jump(ic, RelocInfo::CODE_TARGET);
4248 4260
4249 __ bind(&transition_elements_kind); 4261 __ bind(&transition_elements_kind);
4250 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 4262 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
4251 __ Jump(ic_miss, RelocInfo::CODE_TARGET); 4263 __ Jump(ic_miss, RelocInfo::CODE_TARGET);
4264
4265 if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
4266 // Grow the array by a single element if possible.
4267 __ bind(&grow);
4268
4269 // Make sure the array is only growing by a single element, anything else
4270 // must be handled by the runtime.
4271 __ Branch(&miss_force_generic, ne, key_reg, Operand(scratch));
4272
4273 // Check for the empty array, and preallocate a small backing store if
4274 // possible.
4275 __ lw(length_reg,
4276 FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
4277 __ lw(elements_reg,
4278 FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
4279 __ LoadRoot(at, Heap::kEmptyFixedArrayRootIndex);
4280 __ Branch(&check_capacity, ne, elements_reg, Operand(at));
4281
4282 int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements);
4283 __ AllocateInNewSpace(size, elements_reg, scratch, scratch2, &slow,
4284 TAG_OBJECT);
4285
4286 __ LoadRoot(scratch, Heap::kFixedArrayMapRootIndex);
4287 __ sw(scratch, FieldMemOperand(elements_reg, JSObject::kMapOffset));
4288 __ li(scratch, Operand(Smi::FromInt(JSArray::kPreallocatedArrayElements)));
4289 __ sw(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
4290 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
4291 for (int i = 1; i < JSArray::kPreallocatedArrayElements; ++i) {
4292 __ sw(scratch, FieldMemOperand(elements_reg, FixedArray::SizeFor(i)));
4293 }
4294
4295 // Store the element at index zero.
4296 __ sw(value_reg, FieldMemOperand(elements_reg, FixedArray::SizeFor(0)));
4297
4298 // Install the new backing store in the JSArray.
4299 __ sw(elements_reg,
4300 FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
4301 __ RecordWriteField(receiver_reg, JSObject::kElementsOffset, elements_reg,
4302 scratch, kRAHasNotBeenSaved, kDontSaveFPRegs,
4303 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
4304
4305 // Increment the length of the array.
4306 __ li(length_reg, Operand(Smi::FromInt(1)));
4307 __ sw(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
4308 __ Ret();
4309
4310 __ bind(&check_capacity);
4311 // Check for cow elements, in general they are not handled by this stub
4312 __ CheckMap(elements_reg,
4313 scratch,
4314 Heap::kFixedCOWArrayMapRootIndex,
4315 &miss_force_generic,
4316 DONT_DO_SMI_CHECK);
4317
4318 __ lw(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
4319 __ Branch(&slow, hs, length_reg, Operand(scratch));
4320
4321 // Grow the array and finish the store.
4322 __ Addu(length_reg, length_reg, Operand(Smi::FromInt(1)));
4323 __ sw(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
4324 __ jmp(&finish_store);
4325
4326 __ bind(&slow);
4327 Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
4328 __ Jump(ic_slow, RelocInfo::CODE_TARGET);
4329 }
4252 } 4330 }
4253 4331
4254 4332
4255 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( 4333 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
4256 MacroAssembler* masm, 4334 MacroAssembler* masm,
4257 bool is_js_array) { 4335 bool is_js_array,
4336 KeyedAccessGrowMode grow_mode) {
4258 // ----------- S t a t e ------------- 4337 // ----------- S t a t e -------------
4259 // -- a0 : value 4338 // -- a0 : value
4260 // -- a1 : key 4339 // -- a1 : key
4261 // -- a2 : receiver 4340 // -- a2 : receiver
4262 // -- ra : return address 4341 // -- ra : return address
4263 // -- a3 : scratch 4342 // -- a3 : scratch
4264 // -- t0 : scratch (elements_reg) 4343 // -- t0 : scratch (elements_reg)
4265 // -- t1 : scratch (mantissa_reg) 4344 // -- t1 : scratch (mantissa_reg)
4266 // -- t2 : scratch (exponent_reg) 4345 // -- t2 : scratch (exponent_reg)
4267 // -- t3 : scratch4 4346 // -- t3 : scratch4
4268 // ----------------------------------- 4347 // -----------------------------------
4269 Label miss_force_generic, transition_elements_kind; 4348 Label miss_force_generic, transition_elements_kind, grow, slow;
4349 Label finish_store, check_capacity;
4270 4350
4271 Register value_reg = a0; 4351 Register value_reg = a0;
4272 Register key_reg = a1; 4352 Register key_reg = a1;
4273 Register receiver_reg = a2; 4353 Register receiver_reg = a2;
4274 Register elements_reg = a3; 4354 Register elements_reg = a3;
4275 Register scratch1 = t0; 4355 Register scratch1 = t0;
4276 Register scratch2 = t1; 4356 Register scratch2 = t1;
4277 Register scratch3 = t2; 4357 Register scratch3 = t2;
4278 Register scratch4 = t3; 4358 Register scratch4 = t3;
4359 Register length_reg = t3;
4279 4360
4280 // This stub is meant to be tail-jumped to, the receiver must already 4361 // This stub is meant to be tail-jumped to, the receiver must already
4281 // have been verified by the caller to not be a smi. 4362 // have been verified by the caller to not be a smi.
4282 __ JumpIfNotSmi(key_reg, &miss_force_generic); 4363 __ JumpIfNotSmi(key_reg, &miss_force_generic);
4283 4364
4284 __ lw(elements_reg, 4365 __ lw(elements_reg,
4285 FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 4366 FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
4286 4367
4287 // Check that the key is within bounds. 4368 // Check that the key is within bounds.
4288 if (is_js_array) { 4369 if (is_js_array) {
4289 __ lw(scratch1, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 4370 __ lw(scratch1, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
4290 } else { 4371 } else {
4291 __ lw(scratch1, 4372 __ lw(scratch1,
4292 FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); 4373 FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
4293 } 4374 }
4294 // Compare smis, unsigned compare catches both negative and out-of-bound 4375 // Compare smis, unsigned compare catches both negative and out-of-bound
4295 // indexes. 4376 // indexes.
4296 __ Branch(&miss_force_generic, hs, key_reg, Operand(scratch1)); 4377 if (grow_mode == ALLOW_JSARRAY_GROWTH) {
4378 __ Branch(&grow, hs, key_reg, Operand(scratch1));
4379 } else {
4380 __ Branch(&miss_force_generic, hs, key_reg, Operand(scratch1));
4381 }
4382
4383 __ bind(&finish_store);
4297 4384
4298 __ StoreNumberToDoubleElements(value_reg, 4385 __ StoreNumberToDoubleElements(value_reg,
4299 key_reg, 4386 key_reg,
4300 receiver_reg, 4387 receiver_reg,
4301 elements_reg, 4388 elements_reg,
4302 scratch1, 4389 scratch1,
4303 scratch2, 4390 scratch2,
4304 scratch3, 4391 scratch3,
4305 scratch4, 4392 scratch4,
4306 &transition_elements_kind); 4393 &transition_elements_kind);
4307 4394
4308 __ Ret(USE_DELAY_SLOT); 4395 __ Ret(USE_DELAY_SLOT);
4309 __ mov(v0, value_reg); // In delay slot. 4396 __ mov(v0, value_reg); // In delay slot.
4310 4397
4311 // Handle store cache miss, replacing the ic with the generic stub. 4398 // Handle store cache miss, replacing the ic with the generic stub.
4312 __ bind(&miss_force_generic); 4399 __ bind(&miss_force_generic);
4313 Handle<Code> ic = 4400 Handle<Code> ic =
4314 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 4401 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
4315 __ Jump(ic, RelocInfo::CODE_TARGET); 4402 __ Jump(ic, RelocInfo::CODE_TARGET);
4316 4403
4317 __ bind(&transition_elements_kind); 4404 __ bind(&transition_elements_kind);
4318 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 4405 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
4319 __ Jump(ic_miss, RelocInfo::CODE_TARGET); 4406 __ Jump(ic_miss, RelocInfo::CODE_TARGET);
4407
4408 if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
4409 // Grow the array by a single element if possible.
4410 __ bind(&grow);
4411
4412 // Make sure the array is only growing by a single element, anything else
4413 // must be handled by the runtime.
4414 __ Branch(&miss_force_generic, ne, key_reg, Operand(scratch1));
4415
4416 // Transition on values that can't be stored in a FixedDoubleArray.
4417 Label value_is_smi;
4418 __ JumpIfSmi(value_reg, &value_is_smi);
4419 __ lw(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
4420 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
4421 __ Branch(&transition_elements_kind, ne, scratch1, Operand(at));
4422 __ bind(&value_is_smi);
4423
4424 // Check for the empty array, and preallocate a small backing store if
4425 // possible.
4426 __ lw(length_reg,
4427 FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
4428 __ lw(elements_reg,
4429 FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
4430 __ LoadRoot(at, Heap::kEmptyFixedArrayRootIndex);
4431 __ Branch(&check_capacity, ne, elements_reg, Operand(at));
4432
4433 int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements);
4434 __ AllocateInNewSpace(size, elements_reg, scratch1, scratch2, &slow,
4435 TAG_OBJECT);
4436
4437 // Initialize the new FixedDoubleArray. Leave elements unitialized for
4438 // efficiency, they are guaranteed to be initialized before use.
4439 __ LoadRoot(scratch1, Heap::kFixedDoubleArrayMapRootIndex);
4440 __ sw(scratch1, FieldMemOperand(elements_reg, JSObject::kMapOffset));
4441 __ li(scratch1, Operand(Smi::FromInt(JSArray::kPreallocatedArrayElements)));
4442 __ sw(scratch1,
4443 FieldMemOperand(elements_reg, FixedDoubleArray::kLengthOffset));
4444
4445 // Install the new backing store in the JSArray.
4446 __ sw(elements_reg,
4447 FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
4448 __ RecordWriteField(receiver_reg, JSObject::kElementsOffset, elements_reg,
4449 scratch1, kRAHasNotBeenSaved, kDontSaveFPRegs,
4450 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
4451
4452 // Increment the length of the array.
4453 __ li(length_reg, Operand(Smi::FromInt(1)));
4454 __ sw(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
4455 __ jmp(&finish_store);
4456
4457 __ bind(&check_capacity);
4458 // Make sure that the backing store can hold additional elements.
4459 __ lw(scratch1,
4460 FieldMemOperand(elements_reg, FixedDoubleArray::kLengthOffset));
4461 __ Branch(&slow, hs, length_reg, Operand(scratch1));
4462
4463 // Grow the array and finish the store.
4464 __ Addu(length_reg, length_reg, Operand(Smi::FromInt(1)));
4465 __ sw(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
4466 __ jmp(&finish_store);
4467
4468 __ bind(&slow);
4469 Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
4470 __ Jump(ic_slow, RelocInfo::CODE_TARGET);
4471 }
4320 } 4472 }
4321 4473
4322 4474
4323 #undef __ 4475 #undef __
4324 4476
4325 } } // namespace v8::internal 4477 } } // namespace v8::internal
4326 4478
4327 #endif // V8_TARGET_ARCH_MIPS 4479 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « src/mips/codegen-mips.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698