| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #if V8_TARGET_ARCH_X87 | 5 #if V8_TARGET_ARCH_X87 |
| 6 | 6 |
| 7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
| 8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 4229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4240 | 4240 |
| 4241 // value is on the stack already. | 4241 // value is on the stack already. |
| 4242 static void HandlePolymorphicStoreCase(MacroAssembler* masm, Register receiver, | 4242 static void HandlePolymorphicStoreCase(MacroAssembler* masm, Register receiver, |
| 4243 Register key, Register vector, | 4243 Register key, Register vector, |
| 4244 Register slot, Register feedback, | 4244 Register slot, Register feedback, |
| 4245 Label* miss) { | 4245 Label* miss) { |
| 4246 // feedback initially contains the feedback array | 4246 // feedback initially contains the feedback array |
| 4247 Label next, next_loop, prepare_next; | 4247 Label next, next_loop, prepare_next; |
| 4248 Label load_smi_map, compare_map; | 4248 Label load_smi_map, compare_map; |
| 4249 Label start_polymorphic; | 4249 Label start_polymorphic; |
| 4250 ExternalReference virtual_register = |
| 4251 ExternalReference::vector_store_virtual_register(masm->isolate()); |
| 4250 | 4252 |
| 4251 __ push(receiver); | 4253 __ push(receiver); |
| 4252 __ push(vector); | 4254 __ push(vector); |
| 4253 | 4255 |
| 4254 Register receiver_map = receiver; | 4256 Register receiver_map = receiver; |
| 4255 Register cached_map = vector; | 4257 Register cached_map = vector; |
| 4256 | 4258 |
| 4257 // Receiver might not be a heap object. | 4259 // Receiver might not be a heap object. |
| 4258 __ JumpIfSmi(receiver, &load_smi_map); | 4260 __ JumpIfSmi(receiver, &load_smi_map); |
| 4259 __ mov(receiver_map, FieldOperand(receiver, 0)); | 4261 __ mov(receiver_map, FieldOperand(receiver, 0)); |
| 4260 __ bind(&compare_map); | 4262 __ bind(&compare_map); |
| 4261 __ mov(cached_map, FieldOperand(feedback, FixedArray::OffsetOfElementAt(0))); | 4263 __ mov(cached_map, FieldOperand(feedback, FixedArray::OffsetOfElementAt(0))); |
| 4262 | 4264 |
| 4263 // A named keyed store might have a 2 element array, all other cases can count | 4265 // A named keyed store might have a 2 element array, all other cases can count |
| 4264 // on an array with at least 2 {map, handler} pairs, so they can go right | 4266 // on an array with at least 2 {map, handler} pairs, so they can go right |
| 4265 // into polymorphic array handling. | 4267 // into polymorphic array handling. |
| 4266 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); | 4268 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); |
| 4267 __ j(not_equal, &start_polymorphic); | 4269 __ j(not_equal, &start_polymorphic); |
| 4268 | 4270 |
| 4269 // found, now call handler. | 4271 // found, now call handler. |
| 4270 Register handler = feedback; | 4272 Register handler = feedback; |
| 4271 DCHECK(handler.is(VectorStoreICDescriptor::ValueRegister())); | 4273 DCHECK(handler.is(VectorStoreICDescriptor::ValueRegister())); |
| 4272 __ mov(handler, FieldOperand(feedback, FixedArray::OffsetOfElementAt(1))); | 4274 __ mov(handler, FieldOperand(feedback, FixedArray::OffsetOfElementAt(1))); |
| 4273 __ pop(vector); | 4275 __ pop(vector); |
| 4274 __ pop(receiver); | 4276 __ pop(receiver); |
| 4275 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); | 4277 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); |
| 4276 __ xchg(handler, Operand(esp, 0)); | 4278 __ mov(Operand::StaticVariable(virtual_register), handler); |
| 4277 __ ret(0); | 4279 __ pop(handler); // Pop "value". |
| 4280 __ jmp(Operand::StaticVariable(virtual_register)); |
| 4278 | 4281 |
| 4279 // Polymorphic, we have to loop from 2 to N | 4282 // Polymorphic, we have to loop from 2 to N |
| 4280 | 4283 |
| 4281 // TODO(mvstanton): I think there is a bug here, we are assuming the | 4284 // TODO(mvstanton): I think there is a bug here, we are assuming the |
| 4282 // array has more than one map/handler pair, but we call this function in the | 4285 // array has more than one map/handler pair, but we call this function in the |
| 4283 // keyed store with a string key case, where it might be just an array of two | 4286 // keyed store with a string key case, where it might be just an array of two |
| 4284 // elements. | 4287 // elements. |
| 4285 | 4288 |
| 4286 __ bind(&start_polymorphic); | 4289 __ bind(&start_polymorphic); |
| 4287 __ push(key); | 4290 __ push(key); |
| 4288 Register counter = key; | 4291 Register counter = key; |
| 4289 __ mov(counter, Immediate(Smi::FromInt(2))); | 4292 __ mov(counter, Immediate(Smi::FromInt(2))); |
| 4290 __ bind(&next_loop); | 4293 __ bind(&next_loop); |
| 4291 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, | 4294 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, |
| 4292 FixedArray::kHeaderSize)); | 4295 FixedArray::kHeaderSize)); |
| 4293 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); | 4296 __ cmp(receiver_map, FieldOperand(cached_map, WeakCell::kValueOffset)); |
| 4294 __ j(not_equal, &prepare_next); | 4297 __ j(not_equal, &prepare_next); |
| 4295 __ mov(handler, FieldOperand(feedback, counter, times_half_pointer_size, | 4298 __ mov(handler, FieldOperand(feedback, counter, times_half_pointer_size, |
| 4296 FixedArray::kHeaderSize + kPointerSize)); | 4299 FixedArray::kHeaderSize + kPointerSize)); |
| 4300 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); |
| 4297 __ pop(key); | 4301 __ pop(key); |
| 4298 __ pop(vector); | 4302 __ pop(vector); |
| 4299 __ pop(receiver); | 4303 __ pop(receiver); |
| 4300 __ lea(handler, FieldOperand(handler, Code::kHeaderSize)); | 4304 __ mov(Operand::StaticVariable(virtual_register), handler); |
| 4301 __ xchg(handler, Operand(esp, 0)); | 4305 __ pop(handler); // Pop "value". |
| 4302 __ ret(0); | 4306 __ jmp(Operand::StaticVariable(virtual_register)); |
| 4303 | 4307 |
| 4304 __ bind(&prepare_next); | 4308 __ bind(&prepare_next); |
| 4305 __ add(counter, Immediate(Smi::FromInt(2))); | 4309 __ add(counter, Immediate(Smi::FromInt(2))); |
| 4306 __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset)); | 4310 __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset)); |
| 4307 __ j(less, &next_loop); | 4311 __ j(less, &next_loop); |
| 4308 | 4312 |
| 4309 // We exhausted our array of map handler pairs. | 4313 // We exhausted our array of map handler pairs. |
| 4310 __ pop(key); | 4314 __ pop(key); |
| 4311 __ pop(vector); | 4315 __ pop(vector); |
| 4312 __ pop(receiver); | 4316 __ pop(receiver); |
| 4313 __ jmp(miss); | 4317 __ jmp(miss); |
| 4314 | 4318 |
| 4315 __ bind(&load_smi_map); | 4319 __ bind(&load_smi_map); |
| 4316 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); | 4320 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); |
| 4317 __ jmp(&compare_map); | 4321 __ jmp(&compare_map); |
| 4318 } | 4322 } |
| 4319 | 4323 |
| 4320 | 4324 |
| 4321 static void HandleMonomorphicStoreCase(MacroAssembler* masm, Register receiver, | 4325 static void HandleMonomorphicStoreCase(MacroAssembler* masm, Register receiver, |
| 4322 Register key, Register vector, | 4326 Register key, Register vector, |
| 4323 Register slot, Register weak_cell, | 4327 Register slot, Register weak_cell, |
| 4324 Label* miss) { | 4328 Label* miss) { |
| 4325 // The store ic value is on the stack. | 4329 // The store ic value is on the stack. |
| 4326 DCHECK(weak_cell.is(VectorStoreICDescriptor::ValueRegister())); | 4330 DCHECK(weak_cell.is(VectorStoreICDescriptor::ValueRegister())); |
| 4331 ExternalReference virtual_register = |
| 4332 ExternalReference::vector_store_virtual_register(masm->isolate()); |
| 4327 | 4333 |
| 4328 // feedback initially contains the feedback array | 4334 // feedback initially contains the feedback array |
| 4329 Label compare_smi_map; | 4335 Label compare_smi_map; |
| 4330 | 4336 |
| 4331 // Move the weak map into the weak_cell register. | 4337 // Move the weak map into the weak_cell register. |
| 4332 Register ic_map = weak_cell; | 4338 Register ic_map = weak_cell; |
| 4333 __ mov(ic_map, FieldOperand(weak_cell, WeakCell::kValueOffset)); | 4339 __ mov(ic_map, FieldOperand(weak_cell, WeakCell::kValueOffset)); |
| 4334 | 4340 |
| 4335 // Receiver might not be a heap object. | 4341 // Receiver might not be a heap object. |
| 4336 __ JumpIfSmi(receiver, &compare_smi_map); | 4342 __ JumpIfSmi(receiver, &compare_smi_map); |
| 4337 __ cmp(ic_map, FieldOperand(receiver, 0)); | 4343 __ cmp(ic_map, FieldOperand(receiver, 0)); |
| 4338 __ j(not_equal, miss); | 4344 __ j(not_equal, miss); |
| 4339 __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size, | 4345 __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size, |
| 4340 FixedArray::kHeaderSize + kPointerSize)); | 4346 FixedArray::kHeaderSize + kPointerSize)); |
| 4341 __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize)); | 4347 __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize)); |
| 4342 // Put the store ic value back in it's register. | 4348 // Put the store ic value back in it's register. |
| 4343 __ xchg(weak_cell, Operand(esp, 0)); | 4349 __ mov(Operand::StaticVariable(virtual_register), weak_cell); |
| 4344 // "return" to the handler. | 4350 __ pop(weak_cell); // Pop "value". |
| 4345 __ ret(0); | 4351 // jump to the handler. |
| 4352 __ jmp(Operand::StaticVariable(virtual_register)); |
| 4346 | 4353 |
| 4347 // In microbenchmarks, it made sense to unroll this code so that the call to | 4354 // In microbenchmarks, it made sense to unroll this code so that the call to |
| 4348 // the handler is duplicated for a HeapObject receiver and a Smi receiver. | 4355 // the handler is duplicated for a HeapObject receiver and a Smi receiver. |
| 4349 __ bind(&compare_smi_map); | 4356 __ bind(&compare_smi_map); |
| 4350 __ CompareRoot(ic_map, Heap::kHeapNumberMapRootIndex); | 4357 __ CompareRoot(ic_map, Heap::kHeapNumberMapRootIndex); |
| 4351 __ j(not_equal, miss); | 4358 __ j(not_equal, miss); |
| 4352 __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size, | 4359 __ mov(weak_cell, FieldOperand(vector, slot, times_half_pointer_size, |
| 4353 FixedArray::kHeaderSize + kPointerSize)); | 4360 FixedArray::kHeaderSize + kPointerSize)); |
| 4354 __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize)); | 4361 __ lea(weak_cell, FieldOperand(weak_cell, Code::kHeaderSize)); |
| 4355 // Put the store ic value back in it's register. | 4362 __ mov(Operand::StaticVariable(virtual_register), weak_cell); |
| 4356 __ xchg(weak_cell, Operand(esp, 0)); | 4363 __ pop(weak_cell); // Pop "value". |
| 4357 // "return" to the handler. | 4364 // jump to the handler. |
| 4358 __ ret(0); | 4365 __ jmp(Operand::StaticVariable(virtual_register)); |
| 4359 } | 4366 } |
| 4360 | 4367 |
| 4361 | 4368 |
| 4362 void VectorStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { | 4369 void VectorStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { |
| 4363 Register receiver = VectorStoreICDescriptor::ReceiverRegister(); // edx | 4370 Register receiver = VectorStoreICDescriptor::ReceiverRegister(); // edx |
| 4364 Register key = VectorStoreICDescriptor::NameRegister(); // ecx | 4371 Register key = VectorStoreICDescriptor::NameRegister(); // ecx |
| 4365 Register value = VectorStoreICDescriptor::ValueRegister(); // eax | 4372 Register value = VectorStoreICDescriptor::ValueRegister(); // eax |
| 4366 Register vector = VectorStoreICDescriptor::VectorRegister(); // ebx | 4373 Register vector = VectorStoreICDescriptor::VectorRegister(); // ebx |
| 4367 Register slot = VectorStoreICDescriptor::SlotRegister(); // edi | 4374 Register slot = VectorStoreICDescriptor::SlotRegister(); // edi |
| 4368 Label miss; | 4375 Label miss; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4421 | 4428 |
| 4422 static void HandlePolymorphicKeyedStoreCase(MacroAssembler* masm, | 4429 static void HandlePolymorphicKeyedStoreCase(MacroAssembler* masm, |
| 4423 Register receiver, Register key, | 4430 Register receiver, Register key, |
| 4424 Register vector, Register slot, | 4431 Register vector, Register slot, |
| 4425 Register feedback, Label* miss) { | 4432 Register feedback, Label* miss) { |
| 4426 // feedback initially contains the feedback array | 4433 // feedback initially contains the feedback array |
| 4427 Label next, next_loop, prepare_next; | 4434 Label next, next_loop, prepare_next; |
| 4428 Label load_smi_map, compare_map; | 4435 Label load_smi_map, compare_map; |
| 4429 Label transition_call; | 4436 Label transition_call; |
| 4430 Label pop_and_miss; | 4437 Label pop_and_miss; |
| 4438 ExternalReference virtual_register = |
| 4439 ExternalReference::vector_store_virtual_register(masm->isolate()); |
| 4431 | 4440 |
| 4432 __ push(receiver); | 4441 __ push(receiver); |
| 4433 __ push(vector); | 4442 __ push(vector); |
| 4434 | 4443 |
| 4435 Register receiver_map = receiver; | 4444 Register receiver_map = receiver; |
| 4436 Register cached_map = vector; | 4445 Register cached_map = vector; |
| 4437 | 4446 |
| 4438 // Receiver might not be a heap object. | 4447 // Receiver might not be a heap object. |
| 4439 __ JumpIfSmi(receiver, &load_smi_map); | 4448 __ JumpIfSmi(receiver, &load_smi_map); |
| 4440 __ mov(receiver_map, FieldOperand(receiver, 0)); | 4449 __ mov(receiver_map, FieldOperand(receiver, 0)); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 4457 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, | 4466 __ mov(cached_map, FieldOperand(feedback, counter, times_half_pointer_size, |
| 4458 FixedArray::kHeaderSize + kPointerSize)); | 4467 FixedArray::kHeaderSize + kPointerSize)); |
| 4459 __ CompareRoot(cached_map, Heap::kUndefinedValueRootIndex); | 4468 __ CompareRoot(cached_map, Heap::kUndefinedValueRootIndex); |
| 4460 __ j(not_equal, &transition_call); | 4469 __ j(not_equal, &transition_call); |
| 4461 __ mov(feedback, FieldOperand(feedback, counter, times_half_pointer_size, | 4470 __ mov(feedback, FieldOperand(feedback, counter, times_half_pointer_size, |
| 4462 FixedArray::kHeaderSize + 2 * kPointerSize)); | 4471 FixedArray::kHeaderSize + 2 * kPointerSize)); |
| 4463 __ pop(key); | 4472 __ pop(key); |
| 4464 __ pop(vector); | 4473 __ pop(vector); |
| 4465 __ pop(receiver); | 4474 __ pop(receiver); |
| 4466 __ lea(feedback, FieldOperand(feedback, Code::kHeaderSize)); | 4475 __ lea(feedback, FieldOperand(feedback, Code::kHeaderSize)); |
| 4467 __ xchg(feedback, Operand(esp, 0)); | 4476 __ mov(Operand::StaticVariable(virtual_register), feedback); |
| 4468 __ ret(0); | 4477 __ pop(feedback); // Pop "value". |
| 4478 __ jmp(Operand::StaticVariable(virtual_register)); |
| 4469 | 4479 |
| 4470 __ bind(&transition_call); | 4480 __ bind(&transition_call); |
| 4471 // Oh holy hell this will be tough. | 4481 // Oh holy hell this will be tough. |
| 4472 // The map goes in vector register. | 4482 // The map goes in vector register. |
| 4473 __ mov(receiver, FieldOperand(cached_map, WeakCell::kValueOffset)); | 4483 __ mov(receiver, FieldOperand(cached_map, WeakCell::kValueOffset)); |
| 4474 // The weak cell may have been cleared. | 4484 // The weak cell may have been cleared. |
| 4475 __ JumpIfSmi(receiver, &pop_and_miss); | 4485 __ JumpIfSmi(receiver, &pop_and_miss); |
| 4476 // slot goes on the stack, and holds return address. | 4486 // slot goes on the stack, and holds return address. |
| 4477 __ xchg(slot, Operand(esp, 4 * kPointerSize)); | 4487 __ xchg(slot, Operand(esp, 4 * kPointerSize)); |
| 4478 // Get the handler in value. | 4488 // Get the handler in value. |
| (...skipping 1007 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5486 Operand(ebp, 7 * kPointerSize), NULL); | 5496 Operand(ebp, 7 * kPointerSize), NULL); |
| 5487 } | 5497 } |
| 5488 | 5498 |
| 5489 | 5499 |
| 5490 #undef __ | 5500 #undef __ |
| 5491 | 5501 |
| 5492 } // namespace internal | 5502 } // namespace internal |
| 5493 } // namespace v8 | 5503 } // namespace v8 |
| 5494 | 5504 |
| 5495 #endif // V8_TARGET_ARCH_X87 | 5505 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |