| OLD | NEW |
| 1 // Copyright 2014 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 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_IA32 | 7 #if V8_TARGET_ARCH_X87 |
| 8 | 8 |
| 9 #include "src/ic/call-optimization.h" | 9 #include "src/ic/call-optimization.h" |
| 10 #include "src/ic/handler-compiler.h" | 10 #include "src/ic/handler-compiler.h" |
| 11 | 11 |
| 12 namespace v8 { | 12 namespace v8 { |
| 13 namespace internal { | 13 namespace internal { |
| 14 | 14 |
| 15 #define __ ACCESS_MASM(masm) | 15 #define __ ACCESS_MASM(masm) |
| 16 | 16 |
| 17 | 17 |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 | 319 |
| 320 static void CompileCallLoadPropertyWithInterceptor( | 320 static void CompileCallLoadPropertyWithInterceptor( |
| 321 MacroAssembler* masm, Register receiver, Register holder, Register name, | 321 MacroAssembler* masm, Register receiver, Register holder, Register name, |
| 322 Handle<JSObject> holder_obj, IC::UtilityId id) { | 322 Handle<JSObject> holder_obj, IC::UtilityId id) { |
| 323 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 323 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
| 324 __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()), | 324 __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()), |
| 325 NamedLoadHandlerCompiler::kInterceptorArgsLength); | 325 NamedLoadHandlerCompiler::kInterceptorArgsLength); |
| 326 } | 326 } |
| 327 | 327 |
| 328 | 328 |
| 329 static void StoreIC_PushArgs(MacroAssembler* masm) { | |
| 330 Register receiver = StoreIC::ReceiverRegister(); | |
| 331 Register name = StoreIC::NameRegister(); | |
| 332 Register value = StoreIC::ValueRegister(); | |
| 333 | |
| 334 DCHECK(!ebx.is(receiver) && !ebx.is(name) && !ebx.is(value)); | |
| 335 | |
| 336 __ pop(ebx); | |
| 337 __ push(receiver); | |
| 338 __ push(name); | |
| 339 __ push(value); | |
| 340 __ push(ebx); | |
| 341 } | |
| 342 | |
| 343 | |
| 344 void NamedStoreHandlerCompiler::GenerateSlow(MacroAssembler* masm) { | |
| 345 // Return address is on the stack. | |
| 346 StoreIC_PushArgs(masm); | |
| 347 | |
| 348 // Do tail-call to runtime routine. | |
| 349 ExternalReference ref(IC_Utility(IC::kStoreIC_Slow), masm->isolate()); | |
| 350 __ TailCallExternalReference(ref, 3, 1); | |
| 351 } | |
| 352 | |
| 353 | |
| 354 void ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) { | |
| 355 // Return address is on the stack. | |
| 356 StoreIC_PushArgs(masm); | |
| 357 | |
| 358 // Do tail-call to runtime routine. | |
| 359 ExternalReference ref(IC_Utility(IC::kKeyedStoreIC_Slow), masm->isolate()); | |
| 360 __ TailCallExternalReference(ref, 3, 1); | |
| 361 } | |
| 362 | |
| 363 | |
| 364 #undef __ | 329 #undef __ |
| 365 #define __ ACCESS_MASM(masm()) | 330 #define __ ACCESS_MASM(masm()) |
| 366 | 331 |
| 367 | 332 |
| 368 void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, | 333 void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, |
| 369 Handle<Name> name) { | 334 Handle<Name> name) { |
| 370 if (!label->is_unused()) { | 335 if (!label->is_unused()) { |
| 371 __ bind(label); | 336 __ bind(label); |
| 372 __ mov(this->name(), Immediate(name)); | 337 __ mov(this->name(), Immediate(name)); |
| 373 } | 338 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 __ j(equal, &do_store, Label::kNear); | 373 __ j(equal, &do_store, Label::kNear); |
| 409 } | 374 } |
| 410 __ bind(&do_store); | 375 __ bind(&do_store); |
| 411 } | 376 } |
| 412 } else if (representation.IsDouble()) { | 377 } else if (representation.IsDouble()) { |
| 413 Label do_store, heap_number; | 378 Label do_store, heap_number; |
| 414 __ AllocateHeapNumber(storage_reg, scratch1, scratch2, slow, MUTABLE); | 379 __ AllocateHeapNumber(storage_reg, scratch1, scratch2, slow, MUTABLE); |
| 415 | 380 |
| 416 __ JumpIfNotSmi(value_reg, &heap_number); | 381 __ JumpIfNotSmi(value_reg, &heap_number); |
| 417 __ SmiUntag(value_reg); | 382 __ SmiUntag(value_reg); |
| 418 __ Cvtsi2sd(xmm0, value_reg); | 383 __ push(value_reg); |
| 384 __ fild_s(Operand(esp, 0)); |
| 385 __ pop(value_reg); |
| 419 __ SmiTag(value_reg); | 386 __ SmiTag(value_reg); |
| 420 __ jmp(&do_store); | 387 __ jmp(&do_store); |
| 421 | 388 |
| 422 __ bind(&heap_number); | 389 __ bind(&heap_number); |
| 423 __ CheckMap(value_reg, isolate()->factory()->heap_number_map(), miss_label, | 390 __ CheckMap(value_reg, isolate()->factory()->heap_number_map(), miss_label, |
| 424 DONT_DO_SMI_CHECK); | 391 DONT_DO_SMI_CHECK); |
| 425 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); | 392 __ fld_d(FieldOperand(value_reg, HeapNumber::kValueOffset)); |
| 426 | 393 |
| 427 __ bind(&do_store); | 394 __ bind(&do_store); |
| 428 __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); | 395 __ fstp_d(FieldOperand(storage_reg, HeapNumber::kValueOffset)); |
| 429 } | 396 } |
| 430 | 397 |
| 431 // Stub never generated for objects that require access checks. | 398 // Stub never generated for objects that require access checks. |
| 432 DCHECK(!transition->is_access_check_needed()); | 399 DCHECK(!transition->is_access_check_needed()); |
| 433 | 400 |
| 434 // Perform map transition for the receiver if necessary. | 401 // Perform map transition for the receiver if necessary. |
| 435 if (details.type() == FIELD && | 402 if (details.type() == FIELD && |
| 436 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { | 403 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { |
| 437 // The properties must be extended before we can store the value. | 404 // The properties must be extended before we can store the value. |
| 438 // We jump to a runtime call that extends the properties array. | 405 // We jump to a runtime call that extends the properties array. |
| 439 __ pop(scratch1); // Return address. | 406 __ pop(scratch1); // Return address. |
| 440 __ push(receiver_reg); | 407 __ push(receiver_reg); |
| 441 __ push(Immediate(transition)); | 408 __ push(Immediate(transition)); |
| 442 __ push(value_reg); | 409 __ push(value_reg); |
| 443 __ push(scratch1); | 410 __ push(scratch1); |
| 444 __ TailCallExternalReference( | 411 __ TailCallExternalReference( |
| 445 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 412 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
| 446 isolate()), | 413 isolate()), |
| 447 3, 1); | 414 3, 1); |
| 448 return; | 415 return; |
| 449 } | 416 } |
| 450 | 417 |
| 451 // Update the map of the object. | 418 // Update the map of the object. |
| 452 __ mov(scratch1, Immediate(transition)); | 419 __ mov(scratch1, Immediate(transition)); |
| 453 __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset), scratch1); | 420 __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset), scratch1); |
| 454 | 421 |
| 455 // Update the write barrier for the map field. | 422 // Update the write barrier for the map field. |
| 456 __ RecordWriteField(receiver_reg, HeapObject::kMapOffset, scratch1, scratch2, | 423 __ RecordWriteField(receiver_reg, HeapObject::kMapOffset, scratch1, scratch2, |
| 457 kDontSaveFPRegs, OMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | 424 OMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
| 458 | 425 |
| 459 if (details.type() == CONSTANT) { | 426 if (details.type() == CONSTANT) { |
| 460 DCHECK(value_reg.is(eax)); | 427 DCHECK(value_reg.is(eax)); |
| 461 __ ret(0); | 428 __ ret(0); |
| 462 return; | 429 return; |
| 463 } | 430 } |
| 464 | 431 |
| 465 int index = transition->instance_descriptors()->GetFieldIndex( | 432 int index = transition->instance_descriptors()->GetFieldIndex( |
| 466 transition->LastAdded()); | 433 transition->LastAdded()); |
| 467 | 434 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 481 } else { | 448 } else { |
| 482 __ mov(FieldOperand(receiver_reg, offset), value_reg); | 449 __ mov(FieldOperand(receiver_reg, offset), value_reg); |
| 483 } | 450 } |
| 484 | 451 |
| 485 if (!representation.IsSmi()) { | 452 if (!representation.IsSmi()) { |
| 486 // Update the write barrier for the array address. | 453 // Update the write barrier for the array address. |
| 487 if (!representation.IsDouble()) { | 454 if (!representation.IsDouble()) { |
| 488 __ mov(storage_reg, value_reg); | 455 __ mov(storage_reg, value_reg); |
| 489 } | 456 } |
| 490 __ RecordWriteField(receiver_reg, offset, storage_reg, scratch1, | 457 __ RecordWriteField(receiver_reg, offset, storage_reg, scratch1, |
| 491 kDontSaveFPRegs, EMIT_REMEMBERED_SET, smi_check); | 458 EMIT_REMEMBERED_SET, smi_check); |
| 492 } | 459 } |
| 493 } else { | 460 } else { |
| 494 // Write to the properties array. | 461 // Write to the properties array. |
| 495 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 462 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
| 496 // Get the properties array (optimistically). | 463 // Get the properties array (optimistically). |
| 497 __ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); | 464 __ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); |
| 498 if (representation.IsDouble()) { | 465 if (representation.IsDouble()) { |
| 499 __ mov(FieldOperand(scratch1, offset), storage_reg); | 466 __ mov(FieldOperand(scratch1, offset), storage_reg); |
| 500 } else { | 467 } else { |
| 501 __ mov(FieldOperand(scratch1, offset), value_reg); | 468 __ mov(FieldOperand(scratch1, offset), value_reg); |
| 502 } | 469 } |
| 503 | 470 |
| 504 if (!representation.IsSmi()) { | 471 if (!representation.IsSmi()) { |
| 505 // Update the write barrier for the array address. | 472 // Update the write barrier for the array address. |
| 506 if (!representation.IsDouble()) { | 473 if (!representation.IsDouble()) { |
| 507 __ mov(storage_reg, value_reg); | 474 __ mov(storage_reg, value_reg); |
| 508 } | 475 } |
| 509 __ RecordWriteField(scratch1, offset, storage_reg, receiver_reg, | 476 __ RecordWriteField(scratch1, offset, storage_reg, receiver_reg, |
| 510 kDontSaveFPRegs, EMIT_REMEMBERED_SET, smi_check); | 477 EMIT_REMEMBERED_SET, smi_check); |
| 511 } | 478 } |
| 512 } | 479 } |
| 513 | 480 |
| 514 // Return the value (register eax). | 481 // Return the value (register eax). |
| 515 DCHECK(value_reg.is(eax)); | 482 DCHECK(value_reg.is(eax)); |
| 516 __ ret(0); | 483 __ ret(0); |
| 517 } | 484 } |
| 518 | 485 |
| 519 | 486 |
| 520 void NamedStoreHandlerCompiler::GenerateStoreField(LookupIterator* lookup, | 487 void NamedStoreHandlerCompiler::GenerateStoreField(LookupIterator* lookup, |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 887 | 854 |
| 888 // Return the generated code. | 855 // Return the generated code. |
| 889 return GetCode(kind(), Code::NORMAL, name); | 856 return GetCode(kind(), Code::NORMAL, name); |
| 890 } | 857 } |
| 891 | 858 |
| 892 | 859 |
| 893 #undef __ | 860 #undef __ |
| 894 } | 861 } |
| 895 } // namespace v8::internal | 862 } // namespace v8::internal |
| 896 | 863 |
| 897 #endif // V8_TARGET_ARCH_IA32 | 864 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |