Revision: 10384
Author:   [email protected]
Date:     Wed Jan 11 02:35:37 2012
Log:      Support inlining and crankshaft optimization of Math.random.

[email protected]
BUG=
TEST=

Review URL: http://codereview.chromium.org/9167011
http://code.google.com/p/v8/source/detail?r=10384

Modified:
 /branches/bleeding_edge/src/arm/lithium-arm.cc
 /branches/bleeding_edge/src/arm/lithium-arm.h
 /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
 /branches/bleeding_edge/src/hydrogen-instructions.h
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-ia32.h
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc
 /branches/bleeding_edge/src/x64/lithium-x64.cc
 /branches/bleeding_edge/src/x64/lithium-x64.h

=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc      Wed Jan 11 00:29:42 2012
+++ /branches/bleeding_edge/src/arm/lithium-arm.cc      Wed Jan 11 02:35:37 2012
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -1425,6 +1425,15 @@
                     instr,
                     CAN_DEOPTIMIZE_EAGERLY);
 }
+
+
+LInstruction* LChunkBuilder::DoRandom(HRandom* instr) {
+  ASSERT(instr->representation().IsDouble());
+  ASSERT(instr->global_object()->representation().IsTagged());
+  LOperand* global_object = UseFixed(instr->global_object(), r0);
+  LRandom* result = new LRandom(global_object);
+  return MarkAsCall(DefineFixedDouble(result, d7), instr);
+}


 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.h       Tue Dec 20 02:57:12 2011
+++ /branches/bleeding_edge/src/arm/lithium-arm.h       Wed Jan 11 02:35:37 2012
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -141,6 +141,7 @@
   V(Parameter)                                  \
   V(Power)                                      \
   V(PushArgument)                               \
+  V(Random)                                     \
   V(RegExpLiteral)                              \
   V(Return)                                     \
   V(ShiftI)                                     \
@@ -1026,6 +1027,17 @@
 };


+class LRandom: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LRandom(LOperand* global_object) {
+    inputs_[0] = global_object;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(Random, "random")
+  DECLARE_HYDROGEN_ACCESSOR(Random)
+};
+
+
 class LArithmeticD: public LTemplateInstruction<1, 2, 0> {
  public:
   LArithmeticD(Token::Value op, LOperand* left, LOperand* right)
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Wed Jan 11 01:39:37 2012 +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Wed Jan 11 02:35:37 2012
@@ -3193,6 +3193,30 @@
     __ CallStub(&stub);
   }
 }
+
+
+void LCodeGen::DoRandom(LRandom* instr) {
+  // Having marked this instruction as a call we can use any
+  // registers.
+  ASSERT(ToDoubleRegister(instr->result()).is(d7));
+  ASSERT(ToRegister(instr->InputAt(0)).is(r0));
+
+  __ PrepareCallCFunction(1, scratch0());
+  __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset));
+ __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
+
+  // 0x41300000 is the top half of 1.0 x 2^20 as a double.
+  // Create this constant using mov/orr to avoid PC relative load.
+  __ mov(r1, Operand(0x41000000));
+  __ orr(r1, r1, Operand(0x300000));
+  // Move 0x41300000xxxxxxxx (x = random bits) to VFP.
+  __ vmov(d7, r0, r1);
+  // Move 0x4130000000000000 to VFP.
+  __ mov(r0, Operand(0, RelocInfo::NONE));
+  __ vmov(d8, r0, r1);
+  // Subtract and store the result in the heap number.
+  __ vsub(d7, d7, d8);
+}


 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Wed Jan 11 02:01:59 2012 +++ /branches/bleeding_edge/src/hydrogen-instructions.h Wed Jan 11 02:35:37 2012
@@ -146,6 +146,7 @@
   V(Parameter)                                 \
   V(Power)                                     \
   V(PushArgument)                              \
+  V(Random)                                    \
   V(RegExpLiteral)                             \
   V(Return)                                    \
   V(Sar)                                       \
@@ -2998,6 +2999,23 @@
 };


+class HRandom: public HTemplateInstruction<1> {
+ public:
+  explicit HRandom(HValue* global_object) {
+    SetOperandAt(0, global_object);
+    set_representation(Representation::Double());
+  }
+
+  HValue* global_object() { return OperandAt(0); }
+
+  virtual Representation RequiredInputRepresentation(int index) {
+    return Representation::Tagged();
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(Random)
+};
+
+
 class HAdd: public HArithmeticBinaryOperation {
  public:
   HAdd(HValue* context, HValue* left, HValue* right)
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Mon Jan  9 08:37:47 2012
+++ /branches/bleeding_edge/src/hydrogen.cc     Wed Jan 11 02:35:37 2012
@@ -5127,6 +5127,18 @@
         ast_context()->ReturnInstruction(result, expr->id());
         return true;
       }
+      break;
+    case kMathRandom:
+      if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) {
+        AddCheckConstantFunction(expr, receiver, receiver_map, true);
+        Drop(1);
+        HValue* context = environment()->LookupContext();
+        HGlobalObject* global_object = new(zone()) HGlobalObject(context);
+        AddInstruction(global_object);
+        HRandom* result = new(zone()) HRandom(global_object);
+        ast_context()->ReturnInstruction(result, expr->id());
+        return true;
+      }
       break;
     default:
       // Not yet supported for inlining.
@@ -6575,7 +6587,11 @@

 // Fast support for Math.random().
 void HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) {
-  return Bailout("inlined runtime function: RandomHeapNumber");
+  HValue* context = environment()->LookupContext();
+  HGlobalObject* global_object = new(zone()) HGlobalObject(context);
+  AddInstruction(global_object);
+  HRandom* result = new(zone()) HRandom(global_object);
+  return ast_context()->ReturnInstruction(result, call->id());
 }


=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Wed Jan 11 01:39:37 2012 +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Wed Jan 11 02:35:37 2012
@@ -3012,6 +3012,29 @@
     __ CallStub(&stub);
   }
 }
+
+
+void LCodeGen::DoRandom(LRandom* instr) {
+  // Having marked this instruction as a call we can use any
+  // registers.
+  ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
+  ASSERT(ToRegister(instr->InputAt(0)).is(eax));
+
+  __ PrepareCallCFunction(1, ebx);
+  __ mov(eax, FieldOperand(eax, GlobalObject::kGlobalContextOffset));
+  __ mov(Operand(esp, 0), eax);
+ __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
+
+  // Convert 32 random bits in eax to 0.(32 random bits) in a double
+  // by computing:
+  // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
+  __ mov(ebx, Immediate(0x49800000));  // 1.0 x 2^20 as single.
+  __ movd(xmm2, ebx);
+  __ movd(xmm1, eax);
+  __ cvtss2sd(xmm2, xmm2);
+  __ xorps(xmm1, xmm2);
+  __ subsd(xmm1, xmm2);
+}


 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.cc Wed Jan 11 00:29:42 2012 +++ /branches/bleeding_edge/src/ia32/lithium-ia32.cc Wed Jan 11 02:35:37 2012
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -1467,6 +1467,15 @@
   return MarkAsCall(DefineFixedDouble(result, xmm3), instr,
                     CAN_DEOPTIMIZE_EAGERLY);
 }
+
+
+LInstruction* LChunkBuilder::DoRandom(HRandom* instr) {
+  ASSERT(instr->representation().IsDouble());
+  ASSERT(instr->global_object()->representation().IsTagged());
+  LOperand* global_object = UseFixed(instr->global_object(), eax);
+  LRandom* result = new(zone()) LRandom(global_object);
+  return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
+}


 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.h     Tue Dec 20 02:57:12 2011
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.h     Wed Jan 11 02:35:37 2012
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -135,6 +135,7 @@
   V(OuterContext)                               \
   V(Parameter)                                  \
   V(Power)                                      \
+  V(Random)                                     \
   V(PushArgument)                               \
   V(RegExpLiteral)                              \
   V(Return)                                     \
@@ -1043,6 +1044,17 @@
 };


+class LRandom: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LRandom(LOperand* global_object) {
+    inputs_[0] = global_object;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(Random, "random")
+  DECLARE_HYDROGEN_ACCESSOR(Random)
+};
+
+
 class LArithmeticD: public LTemplateInstruction<1, 2, 0> {
  public:
   LArithmeticD(Token::Value op, LOperand* left, LOperand* right)
=======================================
--- /branches/bleeding_edge/src/objects.h       Tue Jan 10 08:11:33 2012
+++ /branches/bleeding_edge/src/objects.h       Wed Jan 11 02:35:37 2012
@@ -4893,7 +4893,8 @@
   V(Math, atan, MathATan)                           \
   V(Math, exp, MathExp)                             \
   V(Math, sqrt, MathSqrt)                           \
-  V(Math, pow, MathPow)
+  V(Math, pow, MathPow)                             \
+  V(Math, random, MathRandom)


 enum BuiltinFunctionId {
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Wed Jan 11 01:39:37 2012 +++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Wed Jan 11 02:35:37 2012
@@ -2929,6 +2929,38 @@
     __ CallStub(&stub);
   }
 }
+
+
+void LCodeGen::DoRandom(LRandom* instr) {
+  // Having marked this instruction as a call we can use any
+  // registers.
+  ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
+
+  // Choose the right register for the first argument depending on
+  // calling convention.
+#ifdef _WIN64
+  ASSERT(ToRegister(instr->InputAt(0)).is(rcx));
+  Register global_object = rcx;
+#else
+  ASSERT(ToRegister(instr->InputAt(0)).is(rdi));
+  Register global_object = rdi;
+#endif
+
+  __ PrepareCallCFunction(1);
+  __ movq(global_object,
+          FieldOperand(global_object, GlobalObject::kGlobalContextOffset));
+ __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
+
+  // Convert 32 random bits in rax to 0.(32 random bits) in a double
+  // by computing:
+  // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
+  __ movl(rcx, Immediate(0x49800000));  // 1.0 x 2^20 as single.
+  __ movd(xmm2, rcx);
+  __ movd(xmm1, rax);
+  __ cvtss2sd(xmm2, xmm2);
+  __ xorps(xmm1, xmm2);
+  __ subsd(xmm1, xmm2);
+}


 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.cc      Wed Jan 11 00:29:42 2012
+++ /branches/bleeding_edge/src/x64/lithium-x64.cc      Wed Jan 11 02:35:37 2012
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -1413,6 +1413,19 @@
   return MarkAsCall(DefineFixedDouble(result, xmm3), instr,
                     CAN_DEOPTIMIZE_EAGERLY);
 }
+
+
+LInstruction* LChunkBuilder::DoRandom(HRandom* instr) {
+  ASSERT(instr->representation().IsDouble());
+  ASSERT(instr->global_object()->representation().IsTagged());
+#ifdef _WIN64
+  LOperand* global_object = UseFixed(instr->global_object(), rcx);
+#else
+  LOperand* global_object = UseFixed(instr->global_object(), rdi);
+#endif
+  LRandom* result = new LRandom(global_object);
+  return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
+}


 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.h       Tue Dec 20 02:57:12 2011
+++ /branches/bleeding_edge/src/x64/lithium-x64.h       Wed Jan 11 02:35:37 2012
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -141,6 +141,7 @@
   V(Parameter)                                  \
   V(Power)                                      \
   V(PushArgument)                               \
+  V(Random)                                     \
   V(RegExpLiteral)                              \
   V(Return)                                     \
   V(ShiftI)                                     \
@@ -1024,6 +1025,17 @@
 };


+class LRandom: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LRandom(LOperand* global_object) {
+    inputs_[0] = global_object;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(Random, "random")
+  DECLARE_HYDROGEN_ACCESSOR(Random)
+};
+
+
 class LArithmeticD: public LTemplateInstruction<1, 2, 0> {
  public:
   LArithmeticD(Token::Value op, LOperand* left, LOperand* right)

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to