[Interpreter] Add tests for adding strings and heap number arithmetic.
authoroth <oth@chromium.org>
Mon, 28 Sep 2015 19:14:16 +0000 (12:14 -0700)
committerCommit bot <commit-bot@chromium.org>
Mon, 28 Sep 2015 19:14:30 +0000 (19:14 +0000)
BUG=v8:4280
LOG=N

Review URL: https://codereview.chromium.org/1374613002

Cr-Commit-Position: refs/heads/master@{#30986}

test/cctest/interpreter/test-interpreter.cc
test/unittests/runtime/runtime-interpreter-unittest.cc

index 81dd15ec6df324c2998705cf99b76af2b81f0729..e2383182915e1aa3a2744ddb079eeee7a82da25c 100644 (file)
@@ -349,109 +349,148 @@ TEST(InterpreterLoadStoreRegisters) {
 }
 
 
-TEST(InterpreterAdd) {
-  HandleAndZoneScope handles;
-  // TODO(rmcilroy): Do add tests for heap numbers and strings once we support
-  // them.
-  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-  builder.set_locals_count(1);
-  builder.set_parameter_count(1);
-  Register reg(0);
-  builder.LoadLiteral(Smi::FromInt(1))
-      .StoreAccumulatorInRegister(reg)
-      .LoadLiteral(Smi::FromInt(2))
-      .BinaryOperation(Token::Value::ADD, reg)
-      .Return();
-  Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
-
-  InterpreterTester tester(handles.main_isolate(), bytecode_array);
-  auto callable = tester.GetCallable<>();
-  Handle<Object> return_val = callable().ToHandleChecked();
-  CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(3));
-}
-
+static const Token::Value kArithmeticOperators[] = {
+    Token::Value::ADD, Token::Value::SUB, Token::Value::MUL, Token::Value::DIV,
+    Token::Value::MOD};
 
-TEST(InterpreterSub) {
-  HandleAndZoneScope handles;
-  // TODO(rmcilroy): Do add tests for heap numbers once we support them.
-  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-  builder.set_locals_count(1);
-  builder.set_parameter_count(1);
-  Register reg(0);
-  builder.LoadLiteral(Smi::FromInt(5))
-      .StoreAccumulatorInRegister(reg)
-      .LoadLiteral(Smi::FromInt(31))
-      .BinaryOperation(Token::Value::SUB, reg)
-      .Return();
-  Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
-  InterpreterTester tester(handles.main_isolate(), bytecode_array);
-  auto callable = tester.GetCallable<>();
-  Handle<Object> return_val = callable().ToHandleChecked();
-  CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(-26));
+static double BinaryOpC(Token::Value op, double lhs, double rhs) {
+  switch (op) {
+    case Token::Value::ADD:
+      return lhs + rhs;
+    case Token::Value::SUB:
+      return lhs - rhs;
+    case Token::Value::MUL:
+      return lhs * rhs;
+    case Token::Value::DIV:
+      return lhs / rhs;
+    case Token::Value::MOD:
+      return std::fmod(lhs, rhs);
+    default:
+      UNREACHABLE();
+      return std::numeric_limits<double>::min();
+  }
 }
 
 
-TEST(InterpreterMul) {
-  HandleAndZoneScope handles;
-  // TODO(rmcilroy): Do add tests for heap numbers once we support them.
-  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-  builder.set_locals_count(1);
-  builder.set_parameter_count(1);
-  Register reg(0);
-  builder.LoadLiteral(Smi::FromInt(111))
-      .StoreAccumulatorInRegister(reg)
-      .LoadLiteral(Smi::FromInt(6))
-      .BinaryOperation(Token::Value::MUL, reg)
-      .Return();
-  Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
+TEST(InterpreterBinaryOpsSmi) {
+  int lhs_inputs[] = {3266, 1024, 0, -17, -18000};
+  int rhs_inputs[] = {3266, 5, 4, 3, 2, 1, -1, -2};
+  for (size_t l = 0; l < arraysize(lhs_inputs); l++) {
+    for (size_t r = 0; r < arraysize(rhs_inputs); r++) {
+      for (size_t o = 0; o < arraysize(kArithmeticOperators); o++) {
+        HandleAndZoneScope handles;
+        i::Factory* factory = handles.main_isolate()->factory();
+        BytecodeArrayBuilder builder(handles.main_isolate(),
+                                     handles.main_zone());
+        builder.set_locals_count(1);
+        builder.set_parameter_count(1);
+        Register reg(0);
+        int lhs = lhs_inputs[l];
+        int rhs = rhs_inputs[l];
+        builder.LoadLiteral(Smi::FromInt(lhs))
+            .StoreAccumulatorInRegister(reg)
+            .LoadLiteral(Smi::FromInt(rhs))
+            .BinaryOperation(kArithmeticOperators[o], reg)
+            .Return();
+        Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
-  InterpreterTester tester(handles.main_isolate(), bytecode_array);
-  auto callable = tester.GetCallable<>();
-  Handle<Object> return_val = callable().ToHandleChecked();
-  CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(666));
+        InterpreterTester tester(handles.main_isolate(), bytecode_array);
+        auto callable = tester.GetCallable<>();
+        Handle<Object> return_value = callable().ToHandleChecked();
+        Handle<Object> expected_value =
+            factory->NewNumber(BinaryOpC(kArithmeticOperators[o], lhs, rhs));
+        CHECK(return_value->SameValue(*expected_value));
+      }
+    }
+  }
 }
 
 
-TEST(InterpreterDiv) {
-  HandleAndZoneScope handles;
-  // TODO(rmcilroy): Do add tests for heap numbers once we support them.
-  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-  builder.set_locals_count(1);
-  builder.set_parameter_count(1);
-  Register reg(0);
-  builder.LoadLiteral(Smi::FromInt(-20))
-      .StoreAccumulatorInRegister(reg)
-      .LoadLiteral(Smi::FromInt(5))
-      .BinaryOperation(Token::Value::DIV, reg)
-      .Return();
-  Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
+TEST(InterpreterBinaryOpsHeapNumber) {
+  double lhs_inputs[] = {3266.101, 1024.12, 0.01, -17.99, -18000.833, 9.1e17};
+  double rhs_inputs[] = {3266.101, 5.999, 4.778, 3.331,  2.643,
+                         1.1,      -1.8,  -2.9,  8.3e-27};
+  for (size_t l = 0; l < arraysize(lhs_inputs); l++) {
+    for (size_t r = 0; r < arraysize(rhs_inputs); r++) {
+      for (size_t o = 0; o < arraysize(kArithmeticOperators); o++) {
+        HandleAndZoneScope handles;
+        i::Factory* factory = handles.main_isolate()->factory();
+        BytecodeArrayBuilder builder(handles.main_isolate(),
+                                     handles.main_zone());
+        builder.set_locals_count(1);
+        builder.set_parameter_count(1);
+        Register reg(0);
+        double lhs = lhs_inputs[l];
+        double rhs = rhs_inputs[l];
+        builder.LoadLiteral(factory->NewNumber(lhs))
+            .StoreAccumulatorInRegister(reg)
+            .LoadLiteral(factory->NewNumber(rhs))
+            .BinaryOperation(kArithmeticOperators[o], reg)
+            .Return();
+        Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
 
-  InterpreterTester tester(handles.main_isolate(), bytecode_array);
-  auto callable = tester.GetCallable<>();
-  Handle<Object> return_val = callable().ToHandleChecked();
-  CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(-4));
+        InterpreterTester tester(handles.main_isolate(), bytecode_array);
+        auto callable = tester.GetCallable<>();
+        Handle<Object> return_value = callable().ToHandleChecked();
+        Handle<Object> expected_value =
+            factory->NewNumber(BinaryOpC(kArithmeticOperators[o], lhs, rhs));
+        CHECK(return_value->SameValue(*expected_value));
+      }
+    }
+  }
 }
 
 
-TEST(InterpreterMod) {
+TEST(InterpreterStringAdd) {
   HandleAndZoneScope handles;
-  // TODO(rmcilroy): Do add tests for heap numbers once we support them.
-  BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
-  builder.set_locals_count(1);
-  builder.set_parameter_count(1);
-  Register reg(0);
-  builder.LoadLiteral(Smi::FromInt(121))
-      .StoreAccumulatorInRegister(reg)
-      .LoadLiteral(Smi::FromInt(100))
-      .BinaryOperation(Token::Value::MOD, reg)
-      .Return();
-  Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
+  i::Factory* factory = handles.main_isolate()->factory();
 
-  InterpreterTester tester(handles.main_isolate(), bytecode_array);
-  auto callable = tester.GetCallable<>();
-  Handle<Object> return_val = callable().ToHandleChecked();
-  CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(21));
+  struct TestCase {
+    Handle<Object> lhs;
+    Handle<Object> rhs;
+    Handle<Object> expected_value;
+  } test_cases[] = {
+      {factory->NewStringFromStaticChars("a"),
+       factory->NewStringFromStaticChars("b"),
+       factory->NewStringFromStaticChars("ab")},
+      {factory->NewStringFromStaticChars("aaaaaa"),
+       factory->NewStringFromStaticChars("b"),
+       factory->NewStringFromStaticChars("aaaaaab")},
+      {factory->NewStringFromStaticChars("aaa"),
+       factory->NewStringFromStaticChars("bbbbb"),
+       factory->NewStringFromStaticChars("aaabbbbb")},
+      {factory->NewStringFromStaticChars(""),
+       factory->NewStringFromStaticChars("b"),
+       factory->NewStringFromStaticChars("b")},
+      {factory->NewStringFromStaticChars("a"),
+       factory->NewStringFromStaticChars(""),
+       factory->NewStringFromStaticChars("a")},
+      {factory->NewStringFromStaticChars("1.11"), factory->NewHeapNumber(2.5),
+       factory->NewStringFromStaticChars("1.112.5")},
+      {factory->NewStringFromStaticChars("-1.11"), factory->NewHeapNumber(2.56),
+       factory->NewStringFromStaticChars("-1.112.56")},
+      {factory->NewStringFromStaticChars(""), factory->NewHeapNumber(2.5),
+       factory->NewStringFromStaticChars("2.5")},
+  };
+
+  for (size_t i = 0; i < arraysize(test_cases); i++) {
+    BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
+    builder.set_locals_count(1);
+    builder.set_parameter_count(1);
+    Register reg(0);
+    builder.LoadLiteral(test_cases[i].lhs)
+        .StoreAccumulatorInRegister(reg)
+        .LoadLiteral(test_cases[i].rhs)
+        .BinaryOperation(Token::Value::ADD, reg)
+        .Return();
+    Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
+
+    InterpreterTester tester(handles.main_isolate(), bytecode_array);
+    auto callable = tester.GetCallable<>();
+    Handle<Object> return_value = callable().ToHandleChecked();
+    CHECK(return_value->SameValue(*test_cases[i].expected_value));
+  }
 }
 
 
index 73f29ba532f44058cdac4ded40dc3fe6c62007be..0c3d414798ba36592127129e3c9c606f5ea0ffb1 100644 (file)
@@ -166,6 +166,7 @@ TEST_F(RuntimeInterpreterTest, ToBoolean) {
   }
 }
 
+
 }  // Namespace interpreter
 }  // namespace internal
 }  // namespace v8