Index: src/ia32/lithium-codegen-ia32.cc |
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc |
index 0f56825783f50f72827f58913d05dfb18f415273..d32f95d3098cd8ed3a3c0153d3adae19acc7ad08 100644 |
--- a/src/ia32/lithium-codegen-ia32.cc |
+++ b/src/ia32/lithium-codegen-ia32.cc |
@@ -1694,7 +1694,7 @@ void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
- // Object and function are in fixed registers eax and edx. |
+ // Object and function are in fixed registers defined by the stub. |
InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
@@ -1720,6 +1720,107 @@ void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { |
} |
+void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { |
+ class DeferredInstanceOfKnownGlobal: public LDeferredCode { |
+ public: |
+ DeferredInstanceOfKnownGlobal(LCodeGen* codegen, |
+ LInstanceOfKnownGlobal* instr) |
+ : LDeferredCode(codegen), instr_(instr) { } |
+ virtual void Generate() { |
+ codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_); |
+ } |
+ |
+ Label* map_check() { return &map_check_; } |
+ |
+ private: |
+ LInstanceOfKnownGlobal* instr_; |
+ Label map_check_; |
+ }; |
+ |
+ DeferredInstanceOfKnownGlobal* deferred; |
+ deferred = new DeferredInstanceOfKnownGlobal(this, instr); |
+ |
+ Label done, false_result; |
+ Register object = ToRegister(instr->input()); |
+ Register temp = ToRegister(instr->temp()); |
+ |
+ // A Smi is not instance of anything. |
+ __ test(object, Immediate(kSmiTagMask)); |
+ __ j(zero, &false_result, not_taken); |
+ |
+ // This is the inlined call site instanceof cache. The two occourences of the |
+ // hole value will be patched to the last map/result pair generated by the |
+ // instanceof stub. |
+ NearLabel cache_miss; |
+ Register map = ToRegister(instr->temp()); |
+ __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); |
+ __ bind(deferred->map_check()); // Label for calculating code patching. |
+ __ cmp(map, Factory::the_hole_value()); // Patched to cached map. |
+ __ j(not_equal, &cache_miss, not_taken); |
+ __ mov(eax, Factory::the_hole_value()); // Patched to either true or false. |
+ __ jmp(&done); |
+ |
+ // The inlined call site cache did not match. Check null and string before |
+ // calling the deferred code. |
+ __ bind(&cache_miss); |
+ // Null is not instance of anything. |
+ __ cmp(object, Factory::null_value()); |
+ __ j(equal, &false_result); |
+ |
+ // String values are not instances of anything. |
+ Condition is_string = masm_->IsObjectStringType(object, temp, temp); |
+ __ j(is_string, &false_result); |
+ |
+ // Go to the deferred code. |
+ __ jmp(deferred->entry()); |
+ |
+ __ bind(&false_result); |
+ __ mov(ToRegister(instr->result()), Factory::false_value()); |
+ |
+ // Here result has either true or false. Deferred code also produces true or |
+ // false object. |
+ __ bind(deferred->exit()); |
+ __ bind(&done); |
+} |
+ |
+ |
+void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, |
+ Label* map_check) { |
+ __ PushSafepointRegisters(); |
+ |
+ InstanceofStub::Flags flags = InstanceofStub::kNoFlags; |
+ flags = static_cast<InstanceofStub::Flags>( |
+ flags | InstanceofStub::kArgsInRegisters); |
+ flags = static_cast<InstanceofStub::Flags>( |
+ flags | InstanceofStub::kCallSiteInlineCheck); |
+ flags = static_cast<InstanceofStub::Flags>( |
+ flags | InstanceofStub::kReturnTrueFalseObject); |
+ InstanceofStub stub(flags); |
+ |
+ // Get the temp register reserved by the instruction. This needs to be edi as |
+ // its slot of the pushing of safepoint registers is used to communicate the |
+ // offset to the location of the map check. |
+ Register temp = ToRegister(instr->temp()); |
+ ASSERT(temp.is(edi)); |
+ __ mov(InstanceofStub::right(), Immediate(instr->function())); |
+ static const int kAdditionalDelta = 13; |
+ int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; |
+ Label before_push_delta; |
+ __ bind(&before_push_delta); |
+ __ mov(temp, Immediate(delta)); |
+ __ mov(Operand(esp, EspIndexForPushAll(temp) * kPointerSize), temp); |
+ __ call(stub.GetCode(), RelocInfo::CODE_TARGET); |
+ ASSERT_EQ(kAdditionalDelta, |
+ masm_->SizeOfCodeGeneratedSince(&before_push_delta)); |
+ RecordSafepointWithRegisters( |
+ instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); |
+ // Put the result value into the eax slot and restore all registers. |
+ __ mov(Operand(esp, EspIndexForPushAll(eax) * kPointerSize), eax); |
+ |
+ __ PopSafepointRegisters(); |
+} |
+ |
+ |
static Condition ComputeCompareCondition(Token::Value op) { |
switch (op) { |
case Token::EQ_STRICT: |
@@ -1899,6 +2000,8 @@ void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
__ sub(length, index); |
DeoptimizeIf(below_equal, instr->environment()); |
+ // There are two words between the frame pointer and the last argument. |
+ // Subtracting from length accounts for one of them add one more. |
__ mov(result, Operand(arguments, length, times_4, kPointerSize)); |
} |
@@ -1948,7 +2051,7 @@ void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
Register result = ToRegister(instr->result()); |
// Check for arguments adapter frame. |
- Label done, adapted; |
+ NearLabel done, adapted; |
__ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
__ mov(result, Operand(result, StandardFrameConstants::kContextOffset)); |
__ cmp(Operand(result), |
@@ -1963,7 +2066,8 @@ void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
__ bind(&adapted); |
__ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
- // Done. Pointer to topmost argument is in result. |
+ // Result is the frame pointer for the frame if not adapted and for the real |
+ // frame below the adaptor frame if adapted. |
__ bind(&done); |
} |
@@ -1972,9 +2076,9 @@ void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { |
Operand elem = ToOperand(instr->input()); |
Register result = ToRegister(instr->result()); |
- Label done; |
+ NearLabel done; |
- // No arguments adaptor frame. Number of arguments is fixed. |
+ // If no arguments adaptor frame the number of arguments is fixed. |
__ cmp(ebp, elem); |
__ mov(result, Immediate(scope()->num_parameters())); |
__ j(equal, &done); |
@@ -1985,7 +2089,7 @@ void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { |
ArgumentsAdaptorFrameConstants::kLengthOffset)); |
__ SmiUntag(result); |
- // Done. Argument length is in result register. |
+ // Argument length is in result register. |
__ bind(&done); |
} |
@@ -2534,7 +2638,6 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { |
value); |
} |
- // Update the write barrier unless we're certain that we're storing a smi. |
if (instr->hydrogen()->NeedsWriteBarrier()) { |
// Compute address of modified element and store it into key register. |
__ lea(key, FieldOperand(elements, key, times_4, FixedArray::kHeaderSize)); |