Version 3.0.7

Stopped calling inherited setters when creating object literals (issue 1015).

Changed interpretation of malformed \c? escapes in RegExp to match JSC.

Enhanced the command-line debugger interface and fixed some minor bugs in the debugger.

Performance improvements on the IA32 platform.

Review URL: http://codereview.chromium.org/6113004

git-svn-id: http://v8.googlecode.com/svn/trunk@6238 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 0f56825..d32f95d 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -1694,7 +1694,7 @@
 
 
 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::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 @@
   __ 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 @@
   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 @@
   __ 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 @@
   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 @@
                          ArgumentsAdaptorFrameConstants::kLengthOffset));
   __ SmiUntag(result);
 
-  // Done. Argument length is in result register.
+  // Argument length is in result register.
   __ bind(&done);
 }
 
@@ -2534,7 +2638,6 @@
            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));