Refactor smi tagging and untagging on IA-32.
authorkasperl@chromium.org <kasperl@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 18 Dec 2009 11:13:33 +0000 (11:13 +0000)
committerkasperl@chromium.org <kasperl@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 18 Dec 2009 11:13:33 +0000 (11:13 +0000)
Review URL: http://codereview.chromium.org/501113

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3493 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/ia32/builtins-ia32.cc
src/ia32/codegen-ia32.cc
src/ia32/macro-assembler-ia32.h
src/ia32/stub-cache-ia32.cc

index f4dd2f9..d56c02d 100644 (file)
@@ -86,7 +86,7 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
   __ EnterConstructFrame();
 
   // Store a smi-tagged arguments count on the stack.
-  __ shl(eax, kSmiTagSize);
+  __ SmiTag(eax);
   __ push(eax);
 
   // Push the function to invoke on the stack.
@@ -255,7 +255,7 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
 
   // Retrieve smi-tagged arguments count from the stack.
   __ mov(eax, Operand(esp, 0));
-  __ shr(eax, kSmiTagSize);
+  __ SmiUntag(eax);
 
   // Push the allocated receiver to the stack. We need two copies
   // because we may have to return the original one and the calling
@@ -440,8 +440,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
     __ EnterInternalFrame();  // preserves eax, ebx, edi
 
     // Store the arguments count on the stack (smi tagged).
-    ASSERT(kSmiTag == 0);
-    __ shl(eax, kSmiTagSize);
+    __ SmiTag(eax);
     __ push(eax);
 
     __ push(edi);  // save edi across the call
@@ -452,7 +451,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
 
     // Get the arguments count and untag it.
     __ pop(eax);
-    __ shr(eax, kSmiTagSize);
+    __ SmiUntag(eax);
 
     __ LeaveInternalFrame();
     __ jmp(&patch_receiver);
@@ -634,7 +633,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
 
   // Invoke the function.
   ParameterCount actual(eax);
-  __ shr(eax, kSmiTagSize);
+  __ SmiUntag(eax);
   __ mov(edi, Operand(ebp, 4 * kPointerSize));
   __ InvokeFunction(edi, actual, CALL_FUNCTION);
 
@@ -831,7 +830,7 @@ static void AllocateJSArray(MacroAssembler* masm,
   // elements_array_end: start of next object
   // array_size: size of array (smi)
   ASSERT(kSmiTag == 0);
-  __ shr(array_size, kSmiTagSize);  // Convert from smi to value.
+  __ SmiUntag(array_size);  // Convert from smi to value.
   __ mov(FieldOperand(elements_array, JSObject::kMapOffset),
          Factory::fixed_array_map());
   Label not_empty_2, fill_array;
@@ -960,7 +959,7 @@ static void ArrayNativeCode(MacroAssembler* masm,
   // Handle construction of an array from a list of arguments.
   __ bind(&argc_two_or_more);
   ASSERT(kSmiTag == 0);
-  __ shl(eax, kSmiTagSize);  // Convet argc to a smi.
+  __ SmiTag(eax);  // Convet argc to a smi.
   // eax: array_size (smi)
   // edi: constructor
   // esp[0] : argc
index b2adfe1..a353693 100644 (file)
@@ -842,9 +842,9 @@ void DeferredInlineBinaryOperation::Generate() {
     __ jmp(&load_right);
 
     __ bind(&left_smi);
-    __ sar(left_, 1);
+    __ SmiUntag(left_);
     __ cvtsi2sd(xmm0, Operand(left_));
-    __ shl(left_, 1);
+    __ SmiTag(left_);
     if (mode_ == OVERWRITE_LEFT) {
       Label alloc_failure;
       __ push(left_);
@@ -870,9 +870,9 @@ void DeferredInlineBinaryOperation::Generate() {
     __ jmp(&do_op);
 
     __ bind(&right_smi);
-    __ sar(right_, 1);
+    __ SmiUntag(right_);
     __ cvtsi2sd(xmm1, Operand(right_));
-    __ shl(right_, 1);
+    __ SmiTag(right_);
     if (mode_ == OVERWRITE_RIGHT || mode_ == NO_OVERWRITE) {
       Label alloc_failure;
       __ push(left_);
@@ -1215,8 +1215,7 @@ void CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
       __ test(edx, Operand(edx));
       deferred->Branch(not_zero);
       // Tag the result and store it in the quotient register.
-      ASSERT(kSmiTagSize == times_2);  // adjust code if not the case
-      __ lea(eax, Operand(eax, eax, times_1, kSmiTag));
+      __ SmiTag(eax);
       deferred->BindExit();
       left->Unuse();
       right->Unuse();
@@ -1276,8 +1275,8 @@ void CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
 
     // Untag both operands.
     __ mov(answer.reg(), left->reg());
-    __ sar(answer.reg(), kSmiTagSize);
-    __ sar(ecx, kSmiTagSize);
+    __ SmiUntag(answer.reg());
+    __ SmiUntag(ecx);
     // Perform the operation.
     switch (op) {
       case Token::SAR:
@@ -1299,8 +1298,7 @@ void CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
         // in a case where it is dropped anyway.
         __ test(answer.reg(), Immediate(0xc0000000));
         __ j(zero, &result_ok);
-        ASSERT(kSmiTag == 0);
-        __ shl(ecx, kSmiTagSize);
+        __ SmiTag(ecx);
         deferred->Jump();
         __ bind(&result_ok);
         break;
@@ -1311,8 +1309,7 @@ void CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
         // Check that the *signed* result fits in a smi.
         __ cmp(answer.reg(), 0xc0000000);
         __ j(positive, &result_ok);
-        ASSERT(kSmiTag == 0);
-        __ shl(ecx, kSmiTagSize);
+        __ SmiTag(ecx);
         deferred->Jump();
         __ bind(&result_ok);
         break;
@@ -1321,9 +1318,7 @@ void CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
         UNREACHABLE();
     }
     // Smi-tag the result in answer.
-    ASSERT(kSmiTagSize == 1);  // Adjust code if not the case.
-    __ lea(answer.reg(),
-           Operand(answer.reg(), answer.reg(), times_1, kSmiTag));
+    __ SmiTag(answer.reg());
     deferred->BindExit();
     left->Unuse();
     right->Unuse();
@@ -1373,7 +1368,7 @@ void CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
       ASSERT(kSmiTag == 0);  // Adjust code below if not the case.
       // Remove smi tag from the left operand (but keep sign).
       // Left-hand operand has been copied into answer.
-      __ sar(answer.reg(), kSmiTagSize);
+      __ SmiUntag(answer.reg());
       // Do multiplication of smis, leaving result in answer.
       __ imul(answer.reg(), Operand(right->reg()));
       // Go slow on overflows.
@@ -1720,7 +1715,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
         __ test(operand->reg(), Immediate(kSmiTagMask));
         deferred->Branch(not_zero);
         __ mov(answer.reg(), operand->reg());
-        __ sar(answer.reg(), kSmiTagSize);
+        __ SmiUntag(answer.reg());
         __ shr(answer.reg(), shift_value);
         // A negative Smi shifted right two is in the positive Smi range.
         if (shift_value < 2) {
@@ -1728,9 +1723,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
           deferred->Branch(not_zero);
         }
         operand->Unuse();
-        ASSERT(kSmiTagSize == times_2);  // Adjust the code if not true.
-        __ lea(answer.reg(),
-               Operand(answer.reg(), answer.reg(), times_1, kSmiTag));
+        __ SmiTag(answer.reg());
         deferred->BindExit();
         frame_->Push(&answer);
       }
@@ -2243,7 +2236,7 @@ void CodeGenerator::CallApplyLazy(Property* apply,
     __ bind(&adapted);
     static const uint32_t kArgumentsLimit = 1 * KB;
     __ mov(eax, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
-    __ shr(eax, kSmiTagSize);
+    __ SmiUntag(eax);
     __ mov(ecx, Operand(eax));
     __ cmp(eax, kArgumentsLimit);
     build_args.Branch(above);
@@ -3270,7 +3263,7 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
   frame_->EmitPush(eax);  // <- slot 3
   frame_->EmitPush(edx);  // <- slot 2
   __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset));
-  __ shl(eax, kSmiTagSize);
+  __ SmiTag(eax);
   frame_->EmitPush(eax);  // <- slot 1
   frame_->EmitPush(Immediate(Smi::FromInt(0)));  // <- slot 0
   entry.Jump();
@@ -3282,7 +3275,7 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
 
   // Push the length of the array and the initial index onto the stack.
   __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
-  __ shl(eax, kSmiTagSize);
+  __ SmiTag(eax);
   frame_->EmitPush(eax);  // <- slot 1
   frame_->EmitPush(Immediate(Smi::FromInt(0)));  // <- slot 0
 
@@ -4447,10 +4440,13 @@ void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
   // Clone the boilerplate object.
   int length = node->values()->length();
   Result clone;
-  if (node->depth() == 1 &&
-      length <= FastCloneShallowArrayStub::kMaximumLength) {
-    FastCloneShallowArrayStub stub(length);
-    clone = frame_->CallStub(&stub, 1);
+  if (node->depth() == 1) {
+    if (length <= FastCloneShallowArrayStub::kMaximumLength) {
+      FastCloneShallowArrayStub stub(length);
+      clone = frame_->CallStub(&stub, 1);
+    } else {
+      clone = frame_->CallRuntime(Runtime::kCloneShallowLiteralBoilerplate, 1);
+    }
   } else {
     clone = frame_->CallRuntime(Runtime::kCloneLiteralBoilerplate, 1);
   }
@@ -5013,8 +5009,7 @@ void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
                                       times_1,
                                       SeqAsciiString::kHeaderSize));
   __ bind(&got_char_code);
-  ASSERT(kSmiTag == 0);
-  __ shl(temp.reg(), kSmiTagSize);
+  __ SmiTag(temp.reg());
   __ jmp(&end);
 
   // Handle non-flat strings.
@@ -7028,7 +7023,7 @@ void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) {
       // If the smi tag is 0 we can just leave the tag on one operand.
       ASSERT(kSmiTag == 0);  // adjust code below if not the case
       // Remove tag from one of the operands (but keep sign).
-      __ sar(eax, kSmiTagSize);
+      __ SmiUntag(eax);
       // Do multiplication.
       __ imul(eax, Operand(ebx));  // multiplication of smis; result in eax
       // Go slow on overflows.
@@ -7052,8 +7047,7 @@ void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) {
       __ test(edx, Operand(edx));
       __ j(not_zero, slow);
       // Tag the result and store it in register eax.
-      ASSERT(kSmiTagSize == times_2);  // adjust code if not the case
-      __ lea(eax, Operand(eax, eax, times_1, kSmiTag));
+      __ SmiTag(eax);
       break;
 
     case Token::MOD:
@@ -7112,8 +7106,7 @@ void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) {
           UNREACHABLE();
       }
       // Tag the result and store it in register eax.
-      ASSERT(kSmiTagSize == times_2);  // adjust code if not the case
-      __ lea(eax, Operand(eax, eax, times_1, kSmiTag));
+      __ SmiTag(eax);
       break;
 
     default:
@@ -7262,8 +7255,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
         __ j(negative, &non_smi_result);
       }
       // Tag smi result and return.
-      ASSERT(kSmiTagSize == times_2);  // adjust code if not the case
-      __ lea(eax, Operand(eax, eax, times_1, kSmiTag));
+      __ SmiTag(eax);
       GenerateReturn(masm);
 
       // All ops except SHR return a signed int32 that we load in a HeapNumber.
@@ -7611,14 +7603,14 @@ void FloatingPointHelper::LoadSse2Operands(MacroAssembler* masm,
   __ j(equal, &load_float_eax);
   __ jmp(not_numbers);  // Argument in eax is not a number.
   __ bind(&load_smi_edx);
-  __ sar(edx, 1);  // Untag smi before converting to float.
+  __ SmiUntag(edx);  // Untag smi before converting to float.
   __ cvtsi2sd(xmm0, Operand(edx));
-  __ shl(edx, 1);  // Retag smi for heap number overwriting test.
+  __ SmiTag(edx);  // Retag smi for heap number overwriting test.
   __ jmp(&load_eax);
   __ bind(&load_smi_eax);
-  __ sar(eax, 1);  // Untag smi before converting to float.
+  __ SmiUntag(eax);  // Untag smi before converting to float.
   __ cvtsi2sd(xmm1, Operand(eax));
-  __ shl(eax, 1);  // Retag smi for heap number overwriting test.
+  __ SmiTag(eax);  // Retag smi for heap number overwriting test.
   __ jmp(&done);
   __ bind(&load_float_eax);
   __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
index 160dbcb..50fe73a 100644 (file)
@@ -142,6 +142,15 @@ class MacroAssembler: public Assembler {
   // jcc instructions (je, ja, jae, jb, jbe, je, and jz).
   void FCmp();
 
+  // Smi tagging support.
+  void SmiTag(Register reg) {
+    ASSERT(kSmiTag == 0);
+    shl(reg, kSmiTagSize);
+  }
+  void SmiUntag(Register reg) {
+    sar(reg, kSmiTagSize);
+  }
+
   // ---------------------------------------------------------------------------
   // Exception handling
 
index 0e83615..1dd5d95 100644 (file)
@@ -236,7 +236,7 @@ void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
   // Load length from the string and convert to a smi.
   __ bind(&load_length);
   __ mov(eax, FieldOperand(receiver, String::kLengthOffset));
-  __ shl(eax, kSmiTagSize);
+  __ SmiTag(eax);
   __ ret(0);
 
   // Check if the object is a JSValue wrapper.