| 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));
|
|
|