SIMD.js Add the other SIMD Phase 1 types.
authorbbudge <bbudge@chromium.org>
Mon, 3 Aug 2015 13:02:39 +0000 (06:02 -0700)
committerCommit bot <commit-bot@chromium.org>
Mon, 3 Aug 2015 13:02:56 +0000 (13:02 +0000)
Adds Int32x4, Bool32x4, Int16x8, Bool16x8, Int8x16, Bool8x16.
Adds Simd128Value base heap object class.
Changes heap/factory construction pattern to use arrays.
Adds replaceLane functions to facilitate testing.

NOPRESUBMIT=true
(presubmit checks erroneously interpret array declaration in macro definition as variable size array.)

LOG=Y
BUG=v8:4124

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

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

57 files changed:
include/v8.h
src/arm/code-stubs-arm.cc
src/arm/lithium-codegen-arm.cc
src/arm64/code-stubs-arm64.cc
src/arm64/lithium-codegen-arm64.cc
src/bootstrapper.cc
src/code-stubs-hydrogen.cc
src/code-stubs.cc
src/contexts.h
src/factory.cc
src/factory.h
src/full-codegen/arm/full-codegen-arm.cc
src/full-codegen/arm64/full-codegen-arm64.cc
src/full-codegen/full-codegen.h
src/full-codegen/ia32/full-codegen-ia32.cc
src/full-codegen/mips/full-codegen-mips.cc
src/full-codegen/mips64/full-codegen-mips64.cc
src/full-codegen/ppc/full-codegen-ppc.cc
src/full-codegen/x64/full-codegen-x64.cc
src/full-codegen/x87/full-codegen-x87.cc
src/harmony-simd.js
src/heap-snapshot-generator.cc
src/heap/heap.cc
src/heap/heap.h
src/heap/objects-visiting.cc
src/hydrogen-instructions.cc
src/ia32/code-stubs-ia32.cc
src/ia32/lithium-codegen-ia32.cc
src/ic/handler-compiler.cc
src/ic/ic-inl.h
src/macros.py
src/messages.js
src/mips/code-stubs-mips.cc
src/mips/lithium-codegen-mips.cc
src/mips64/code-stubs-mips64.cc
src/mips64/lithium-codegen-mips64.cc
src/objects-debug.cc
src/objects-inl.h
src/objects-printer.cc
src/objects.cc
src/objects.h
src/ppc/code-stubs-ppc.cc
src/ppc/lithium-codegen-ppc.cc
src/runtime.js
src/runtime/runtime-simd.cc
src/runtime/runtime.h
src/types.cc
src/utils.h
src/x64/code-stubs-x64.cc
src/x64/lithium-codegen-x64.cc
src/x87/code-stubs-x87.cc
src/x87/lithium-codegen-x87.cc
test/cctest/test-heap-profiler.cc
test/cctest/test-heap.cc
test/cctest/test-simd.cc
test/mjsunit/harmony/simd.js
test/simdjs/harness-adapt.js

index 0bcb311ba17603deabf277e5d79269638aa711ec..9ac1580554239e808cf7f40ce40b15eadd72a8c5 100644 (file)
@@ -6913,7 +6913,7 @@ class Internals {
   static const int kJSObjectHeaderSize = 3 * kApiPointerSize;
   static const int kFixedArrayHeaderSize = 2 * kApiPointerSize;
   static const int kContextHeaderSize = 2 * kApiPointerSize;
-  static const int kContextEmbedderDataIndex = 81;
+  static const int kContextEmbedderDataIndex = 87;
   static const int kFullStringRepresentationMask = 0x07;
   static const int kStringEncodingMask = 0x4;
   static const int kExternalTwoByteRepresentationTag = 0x02;
@@ -6946,10 +6946,10 @@ class Internals {
   static const int kNodeIsIndependentShift = 3;
   static const int kNodeIsPartiallyDependentShift = 4;
 
-  static const int kJSObjectType = 0xb6;
+  static const int kJSObjectType = 0xbc;
   static const int kFirstNonstringType = 0x80;
   static const int kOddballType = 0x83;
-  static const int kForeignType = 0x87;
+  static const int kForeignType = 0x8d;
 
   static const int kUndefinedOddballKind = 5;
   static const int kNullOddballKind = 3;
index 80d01a176d66bee3160036a1509d1a680003ed2e..d0d09934ef10851bfd774343fe94649217f88fdd 100644 (file)
@@ -249,6 +249,7 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow,
   // They are both equal and they are not both Smis so both of them are not
   // Smis.  If it's not a heap number, then return equal.
   if (cond == lt || cond == gt) {
+    Label not_simd;
     // Call runtime on identical JSObjects.
     __ CompareObjectType(r0, r4, r4, FIRST_SPEC_OBJECT_TYPE);
     __ b(ge, slow);
@@ -256,8 +257,11 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow,
     __ cmp(r4, Operand(SYMBOL_TYPE));
     __ b(eq, slow);
     // Call runtime on identical SIMD values since we must throw a TypeError.
-    __ cmp(r4, Operand(FLOAT32X4_TYPE));
-    __ b(eq, slow);
+    __ cmp(r4, Operand(FIRST_SIMD_VALUE_TYPE));
+    __ b(lt, &not_simd);
+    __ cmp(r4, Operand(LAST_SIMD_VALUE_TYPE));
+    __ b(le, slow);
+    __ bind(&not_simd);
     if (is_strong(strength)) {
       // Call the runtime on anything that is converted in the semantics, since
       // we need to throw a TypeError. Smis have already been ruled out.
@@ -271,14 +275,18 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow,
     __ b(eq, &heap_number);
     // Comparing JS objects with <=, >= is complicated.
     if (cond != eq) {
+      Label not_simd;
       __ cmp(r4, Operand(FIRST_SPEC_OBJECT_TYPE));
       __ b(ge, slow);
       // Call runtime on identical symbols since we need to throw a TypeError.
       __ cmp(r4, Operand(SYMBOL_TYPE));
       __ b(eq, slow);
       // Call runtime on identical SIMD values since we must throw a TypeError.
-      __ cmp(r4, Operand(FLOAT32X4_TYPE));
-      __ b(eq, slow);
+      __ cmp(r4, Operand(FIRST_SIMD_VALUE_TYPE));
+      __ b(lt, &not_simd);
+      __ cmp(r4, Operand(LAST_SIMD_VALUE_TYPE));
+      __ b(le, slow);
+      __ bind(&not_simd);
       if (is_strong(strength)) {
         // Call the runtime on anything that is converted in the semantics,
         // since we need to throw a TypeError. Smis and heap numbers have
index 51d56caef78ce68f544351afdc768e3e7fd70057..7af1982eea66122e4d0feeec2bde7e391280ab6a 100644 (file)
@@ -2270,8 +2270,12 @@ void LCodeGen::DoBranch(LBranch* instr) {
 
       if (expected.Contains(ToBooleanStub::SIMD_VALUE)) {
         // SIMD value -> true.
-        __ CompareInstanceType(map, ip, FLOAT32X4_TYPE);
-        __ b(eq, instr->TrueLabel(chunk_));
+        Label not_simd;
+        __ CompareInstanceType(map, ip, FIRST_SIMD_VALUE_TYPE);
+        __ b(lt, &not_simd);
+        __ CompareInstanceType(map, ip, LAST_SIMD_VALUE_TYPE);
+        __ b(le, instr->TrueLabel(chunk_));
+        __ bind(&not_simd);
       }
 
       if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
@@ -5707,6 +5711,36 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
     __ CompareObjectType(input, scratch, no_reg, FLOAT32X4_TYPE);
     final_branch_condition = eq;
 
+  } else if (String::Equals(type_name, factory->int32x4_string())) {
+    __ JumpIfSmi(input, false_label);
+    __ CompareObjectType(input, scratch, no_reg, INT32X4_TYPE);
+    final_branch_condition = eq;
+
+  } else if (String::Equals(type_name, factory->bool32x4_string())) {
+    __ JumpIfSmi(input, false_label);
+    __ CompareObjectType(input, scratch, no_reg, BOOL32X4_TYPE);
+    final_branch_condition = eq;
+
+  } else if (String::Equals(type_name, factory->int16x8_string())) {
+    __ JumpIfSmi(input, false_label);
+    __ CompareObjectType(input, scratch, no_reg, INT16X8_TYPE);
+    final_branch_condition = eq;
+
+  } else if (String::Equals(type_name, factory->bool16x8_string())) {
+    __ JumpIfSmi(input, false_label);
+    __ CompareObjectType(input, scratch, no_reg, BOOL16X8_TYPE);
+    final_branch_condition = eq;
+
+  } else if (String::Equals(type_name, factory->int8x16_string())) {
+    __ JumpIfSmi(input, false_label);
+    __ CompareObjectType(input, scratch, no_reg, INT8X16_TYPE);
+    final_branch_condition = eq;
+
+  } else if (String::Equals(type_name, factory->bool8x16_string())) {
+    __ JumpIfSmi(input, false_label);
+    __ CompareObjectType(input, scratch, no_reg, BOOL8X16_TYPE);
+    final_branch_condition = eq;
+
   } else {
     __ b(false_label);
   }
index b10364163680b158c76cddefe32aff8a4a275a5d..f75539d501501c98976afe7da1c63b8434b8ba43 100644 (file)
@@ -221,6 +221,7 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm, Register left,
   // Smis.  If it's not a heap number, then return equal.
   Register right_type = scratch;
   if ((cond == lt) || (cond == gt)) {
+    Label not_simd;
     // Call runtime on identical JSObjects.  Otherwise return equal.
     __ JumpIfObjectType(right, right_type, right_type, FIRST_SPEC_OBJECT_TYPE,
                         slow, ge);
@@ -228,8 +229,11 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm, Register left,
     __ Cmp(right_type, SYMBOL_TYPE);
     __ B(eq, slow);
     // Call runtime on identical SIMD values since we must throw a TypeError.
-    __ Cmp(right_type, FLOAT32X4_TYPE);
-    __ B(eq, slow);
+    __ Cmp(right_type, FIRST_SIMD_VALUE_TYPE);
+    __ B(lt, &not_simd);
+    __ Cmp(right_type, LAST_SIMD_VALUE_TYPE);
+    __ B(le, slow);
+    __ Bind(&not_simd);
     if (is_strong(strength)) {
       // Call the runtime on anything that is converted in the semantics, since
       // we need to throw a TypeError. Smis have already been ruled out.
@@ -241,6 +245,7 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm, Register left,
   } else if (cond == eq) {
     __ JumpIfHeapNumber(right, &heap_number);
   } else {
+    Label not_simd;
     __ JumpIfObjectType(right, right_type, right_type, HEAP_NUMBER_TYPE,
                         &heap_number);
     // Comparing JS objects with <=, >= is complicated.
@@ -250,8 +255,11 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm, Register left,
     __ Cmp(right_type, SYMBOL_TYPE);
     __ B(eq, slow);
     // Call runtime on identical SIMD values since we must throw a TypeError.
-    __ Cmp(right_type, FLOAT32X4_TYPE);
-    __ B(eq, slow);
+    __ Cmp(right_type, FIRST_SIMD_VALUE_TYPE);
+    __ B(lt, &not_simd);
+    __ Cmp(right_type, LAST_SIMD_VALUE_TYPE);
+    __ B(le, slow);
+    __ Bind(&not_simd);
     if (is_strong(strength)) {
       // Call the runtime on anything that is converted in the semantics,
       // since we need to throw a TypeError. Smis and heap numbers have
index 6fb1088efc71e9b6b27ff9e52c61e2b24369f44c..c4be83277a805fa51045443d99aa8f4a556d20c3 100644 (file)
@@ -1933,8 +1933,12 @@ void LCodeGen::DoBranch(LBranch* instr) {
 
       if (expected.Contains(ToBooleanStub::SIMD_VALUE)) {
         // SIMD value -> true.
-        __ CompareInstanceType(map, scratch, FLOAT32X4_TYPE);
-        __ B(eq, true_label);
+        Label not_simd;
+        __ CompareInstanceType(map, scratch, FIRST_SIMD_VALUE_TYPE);
+        __ B(lt, &not_simd);
+        __ CompareInstanceType(map, scratch, LAST_SIMD_VALUE_TYPE);
+        __ B(le, true_label);
+        __ Bind(&not_simd);
       }
 
       if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
@@ -6002,6 +6006,60 @@ void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
     __ CompareObjectType(value, map, scratch, FLOAT32X4_TYPE);
     EmitBranch(instr, eq);
 
+  } else if (String::Equals(type_name, factory->int32x4_string())) {
+    DCHECK((instr->temp1() != NULL) && (instr->temp2() != NULL));
+    Register map = ToRegister(instr->temp1());
+    Register scratch = ToRegister(instr->temp2());
+
+    __ JumpIfSmi(value, false_label);
+    __ CompareObjectType(value, map, scratch, INT32X4_TYPE);
+    EmitBranch(instr, eq);
+
+  } else if (String::Equals(type_name, factory->bool32x4_string())) {
+    DCHECK((instr->temp1() != NULL) && (instr->temp2() != NULL));
+    Register map = ToRegister(instr->temp1());
+    Register scratch = ToRegister(instr->temp2());
+
+    __ JumpIfSmi(value, false_label);
+    __ CompareObjectType(value, map, scratch, BOOL32X4_TYPE);
+    EmitBranch(instr, eq);
+
+  } else if (String::Equals(type_name, factory->int16x8_string())) {
+    DCHECK((instr->temp1() != NULL) && (instr->temp2() != NULL));
+    Register map = ToRegister(instr->temp1());
+    Register scratch = ToRegister(instr->temp2());
+
+    __ JumpIfSmi(value, false_label);
+    __ CompareObjectType(value, map, scratch, INT16X8_TYPE);
+    EmitBranch(instr, eq);
+
+  } else if (String::Equals(type_name, factory->bool16x8_string())) {
+    DCHECK((instr->temp1() != NULL) && (instr->temp2() != NULL));
+    Register map = ToRegister(instr->temp1());
+    Register scratch = ToRegister(instr->temp2());
+
+    __ JumpIfSmi(value, false_label);
+    __ CompareObjectType(value, map, scratch, BOOL16X8_TYPE);
+    EmitBranch(instr, eq);
+
+  } else if (String::Equals(type_name, factory->int8x16_string())) {
+    DCHECK((instr->temp1() != NULL) && (instr->temp2() != NULL));
+    Register map = ToRegister(instr->temp1());
+    Register scratch = ToRegister(instr->temp2());
+
+    __ JumpIfSmi(value, false_label);
+    __ CompareObjectType(value, map, scratch, INT8X16_TYPE);
+    EmitBranch(instr, eq);
+
+  } else if (String::Equals(type_name, factory->bool8x16_string())) {
+    DCHECK((instr->temp1() != NULL) && (instr->temp2() != NULL));
+    Register map = ToRegister(instr->temp1());
+    Register scratch = ToRegister(instr->temp2());
+
+    __ JumpIfSmi(value, false_label);
+    __ CompareObjectType(value, map, scratch, BOOL8X16_TYPE);
+    EmitBranch(instr, eq);
+
   } else {
     __ B(false_label);
   }
index 838510000832229b37d7b8c1702b03501dcbf0b2..ea9edba4955b72051e81b4a3e738c08ce1e57150 100644 (file)
@@ -1991,13 +1991,16 @@ void Genesis::InitializeGlobal_harmony_simd() {
   DCHECK(simd_object->IsJSObject());
   JSObject::AddProperty(global, name, simd_object, DONT_ENUM);
 
-  Handle<JSFunction> float32x4_function =
-      InstallFunction(simd_object, "Float32x4", JS_VALUE_TYPE, JSValue::kSize,
-                      isolate->initial_object_prototype(), Builtins::kIllegal);
-  // Set the instance class name since InstallFunction only does this when
-  // we install on the GlobalObject.
-  float32x4_function->SetInstanceClassName(*factory->Float32x4_string());
-  native_context()->set_float32x4_function(*float32x4_function);
+// Install SIMD type functions. Set the instance class names since
+// InstallFunction only does this when we install on the GlobalObject.
+#define SIMD128_INSTALL_FUNCTION(name, type, lane_count, lane_type) \
+  Handle<JSFunction> type##_function = InstallFunction(             \
+      simd_object, #name, JS_VALUE_TYPE, JSValue::kSize,            \
+      isolate->initial_object_prototype(), Builtins::kIllegal);     \
+  native_context()->set_##type##_function(*type##_function);        \
+  type##_function->SetInstanceClassName(*factory->name##_string());
+
+  SIMD128_TYPES(SIMD128_INSTALL_FUNCTION)
 }
 
 
index 4afd592ab19a4837451eb41dc6b6302e84cad1b0..b4c74abdd09acfeb38da4567b533491d5573ce52 100644 (file)
@@ -405,19 +405,72 @@ HValue* CodeStubGraphBuilder<TypeofStub>::BuildCodeStub() {
               { Push(Add<HConstant>(factory->float32x4_string())); }
               is_float32x4.Else();
               {
-                // Is it an undetectable object?
-                IfBuilder is_undetectable(this);
-                is_undetectable.If<HIsUndetectableAndBranch>(object);
-                is_undetectable.Then();
+                IfBuilder is_int32x4(this);
+                is_int32x4.If<HCompareNumericAndBranch>(
+                    instance_type, Add<HConstant>(INT32X4_TYPE), Token::EQ);
+                is_int32x4.Then();
+                { Push(Add<HConstant>(factory->int32x4_string())); }
+                is_int32x4.Else();
                 {
-                  // typeof an undetectable object is 'undefined'.
-                  Push(undefined_string);
-                }
-                is_undetectable.Else();
-                {
-                  // For any kind of object not handled above, the spec rule for
-                  // host objects gives that it is okay to return "object".
-                  Push(object_string);
+                  IfBuilder is_bool32x4(this);
+                  is_bool32x4.If<HCompareNumericAndBranch>(
+                      instance_type, Add<HConstant>(BOOL32X4_TYPE), Token::EQ);
+                  is_bool32x4.Then();
+                  { Push(Add<HConstant>(factory->bool32x4_string())); }
+                  is_bool32x4.Else();
+                  {
+                    IfBuilder is_int16x8(this);
+                    is_int16x8.If<HCompareNumericAndBranch>(
+                        instance_type, Add<HConstant>(INT16X8_TYPE), Token::EQ);
+                    is_int16x8.Then();
+                    { Push(Add<HConstant>(factory->int16x8_string())); }
+                    is_int16x8.Else();
+                    {
+                      IfBuilder is_bool16x8(this);
+                      is_bool16x8.If<HCompareNumericAndBranch>(
+                          instance_type, Add<HConstant>(BOOL16X8_TYPE),
+                          Token::EQ);
+                      is_bool16x8.Then();
+                      { Push(Add<HConstant>(factory->bool16x8_string())); }
+                      is_bool16x8.Else();
+                      {
+                        IfBuilder is_int8x16(this);
+                        is_int8x16.If<HCompareNumericAndBranch>(
+                            instance_type, Add<HConstant>(INT8X16_TYPE),
+                            Token::EQ);
+                        is_int8x16.Then();
+                        { Push(Add<HConstant>(factory->int8x16_string())); }
+                        is_int8x16.Else();
+                        {
+                          IfBuilder is_bool8x16(this);
+                          is_bool8x16.If<HCompareNumericAndBranch>(
+                              instance_type, Add<HConstant>(BOOL8X16_TYPE),
+                              Token::EQ);
+                          is_bool8x16.Then();
+                          { Push(Add<HConstant>(factory->bool8x16_string())); }
+                          is_bool8x16.Else();
+                          {
+                            // Is it an undetectable object?
+                            IfBuilder is_undetectable(this);
+                            is_undetectable.If<HIsUndetectableAndBranch>(
+                                object);
+                            is_undetectable.Then();
+                            {
+                              // typeof an undetectable object is 'undefined'.
+                              Push(undefined_string);
+                            }
+                            is_undetectable.Else();
+                            {
+                              // For any kind of object not handled above, the
+                              // spec rule for host objects gives that it is
+                              // okay to return "object".
+                              Push(object_string);
+                            }
+                          }
+                        }
+                      }
+                    }
+                  }
                 }
               }
             }
index cc77389ded708afdb258c1f84d94ef41a0379a54..c7f4d4b63ba0f4cf49c4403a337ee988c6b160c4 100644 (file)
@@ -994,7 +994,7 @@ bool ToBooleanStub::Types::UpdateStatus(Handle<Object> object) {
     Add(HEAP_NUMBER);
     double value = HeapNumber::cast(*object)->value();
     return value != 0 && !std::isnan(value);
-  } else if (object->IsFloat32x4()) {
+  } else if (object->IsSimd128Value()) {
     Add(SIMD_VALUE);
     return true;
   } else {
index 8e8f0b379153b31693196981934278d1ce44b52d..0109267dd3b6a8a9ef38125dcbb7fdbdee7d03fd 100644 (file)
@@ -82,6 +82,12 @@ enum BindingFlags {
   V(STRING_FUNCTION_PROTOTYPE_MAP_INDEX, Map, string_function_prototype_map)   \
   V(SYMBOL_FUNCTION_INDEX, JSFunction, symbol_function)                        \
   V(FLOAT32X4_FUNCTION_INDEX, JSFunction, float32x4_function)                  \
+  V(INT32X4_FUNCTION_INDEX, JSFunction, int32x4_function)                      \
+  V(BOOL32X4_FUNCTION_INDEX, JSFunction, bool32x4_function)                    \
+  V(INT16X8_FUNCTION_INDEX, JSFunction, int16x8_function)                      \
+  V(BOOL16X8_FUNCTION_INDEX, JSFunction, bool16x8_function)                    \
+  V(INT8X16_FUNCTION_INDEX, JSFunction, int8x16_function)                      \
+  V(BOOL8X16_FUNCTION_INDEX, JSFunction, bool8x16_function)                    \
   V(OBJECT_FUNCTION_INDEX, JSFunction, object_function)                        \
   V(JS_OBJECT_STRONG_MAP_INDEX, Map, js_object_strong_map)                     \
   V(INTERNAL_ARRAY_FUNCTION_INDEX, JSFunction, internal_array_function)        \
@@ -349,6 +355,12 @@ class Context: public FixedArray {
     STRING_FUNCTION_PROTOTYPE_MAP_INDEX,
     SYMBOL_FUNCTION_INDEX,
     FLOAT32X4_FUNCTION_INDEX,
+    INT32X4_FUNCTION_INDEX,
+    BOOL32X4_FUNCTION_INDEX,
+    INT16X8_FUNCTION_INDEX,
+    BOOL16X8_FUNCTION_INDEX,
+    INT8X16_FUNCTION_INDEX,
+    BOOL8X16_FUNCTION_INDEX,
     OBJECT_FUNCTION_INDEX,
     JS_OBJECT_STRONG_MAP_INDEX,
     INTERNAL_ARRAY_FUNCTION_INDEX,
index 1d594d3eb5a6eda62470d908f7669c9b30028cbe..2fe18544395afe3529dd800545b0871236b27b28 100644 (file)
@@ -1047,11 +1047,50 @@ Handle<HeapNumber> Factory::NewHeapNumber(double value,
 }
 
 
-Handle<Float32x4> Factory::NewFloat32x4(float w, float x, float y, float z,
+Handle<Float32x4> Factory::NewFloat32x4(float lanes[4],
                                         PretenureFlag pretenure) {
+  CALL_HEAP_FUNCTION(isolate(),
+                     isolate()->heap()->AllocateFloat32x4(lanes, pretenure),
+                     Float32x4);
+}
+
+
+Handle<Int32x4> Factory::NewInt32x4(int32_t lanes[4], PretenureFlag pretenure) {
+  CALL_HEAP_FUNCTION(
+      isolate(), isolate()->heap()->AllocateInt32x4(lanes, pretenure), Int32x4);
+}
+
+
+Handle<Bool32x4> Factory::NewBool32x4(bool lanes[4], PretenureFlag pretenure) {
+  CALL_HEAP_FUNCTION(isolate(),
+                     isolate()->heap()->AllocateBool32x4(lanes, pretenure),
+                     Bool32x4);
+}
+
+
+Handle<Int16x8> Factory::NewInt16x8(int16_t lanes[8], PretenureFlag pretenure) {
   CALL_HEAP_FUNCTION(
-      isolate(), isolate()->heap()->AllocateFloat32x4(w, x, y, z, pretenure),
-      Float32x4);
+      isolate(), isolate()->heap()->AllocateInt16x8(lanes, pretenure), Int16x8);
+}
+
+
+Handle<Bool16x8> Factory::NewBool16x8(bool lanes[8], PretenureFlag pretenure) {
+  CALL_HEAP_FUNCTION(isolate(),
+                     isolate()->heap()->AllocateBool16x8(lanes, pretenure),
+                     Bool16x8);
+}
+
+
+Handle<Int8x16> Factory::NewInt8x16(int8_t lanes[16], PretenureFlag pretenure) {
+  CALL_HEAP_FUNCTION(
+      isolate(), isolate()->heap()->AllocateInt8x16(lanes, pretenure), Int8x16);
+}
+
+
+Handle<Bool8x16> Factory::NewBool8x16(bool lanes[16], PretenureFlag pretenure) {
+  CALL_HEAP_FUNCTION(isolate(),
+                     isolate()->heap()->AllocateBool8x16(lanes, pretenure),
+                     Bool8x16);
 }
 
 
index 9d42130ee1a85bc1facfd865240e0b5c70a512d1..9a595c411566288711fccba9a1a8e68908609b18 100644 (file)
@@ -351,8 +351,20 @@ class Factory final {
   Handle<HeapNumber> NewHeapNumber(double value,
                                    MutableMode mode = IMMUTABLE,
                                    PretenureFlag pretenure = NOT_TENURED);
-  Handle<Float32x4> NewFloat32x4(float w, float x, float y, float z,
+  Handle<Float32x4> NewFloat32x4(float lanes[4],
                                  PretenureFlag pretenure = NOT_TENURED);
+  Handle<Int32x4> NewInt32x4(int32_t lanes[4],
+                             PretenureFlag pretenure = NOT_TENURED);
+  Handle<Bool32x4> NewBool32x4(bool lanes[4],
+                               PretenureFlag pretenure = NOT_TENURED);
+  Handle<Int16x8> NewInt16x8(int16_t lanes[8],
+                             PretenureFlag pretenure = NOT_TENURED);
+  Handle<Bool16x8> NewBool16x8(bool lanes[8],
+                               PretenureFlag pretenure = NOT_TENURED);
+  Handle<Int8x16> NewInt8x16(int8_t lanes[16],
+                             PretenureFlag pretenure = NOT_TENURED);
+  Handle<Bool8x16> NewBool8x16(bool lanes[16],
+                               PretenureFlag pretenure = NOT_TENURED);
 
   // These objects are used by the api to create env-independent data
   // structures in the heap.
index c07438a2db813d366d7da75d4691e29735a98b10..724c8d7c4ab72d23193997404c7f4522af6bd2c6 100644 (file)
@@ -3431,6 +3431,33 @@ void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitIsSimdObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK(args->length() == 1);
+
+  VisitForAccumulatorValue(args->at(0));
+
+  Label materialize_true, materialize_false;
+  Label* if_true = NULL;
+  Label* if_false = NULL;
+  Label* fall_through = NULL;
+  context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
+                         &if_false, &fall_through);
+
+  __ JumpIfSmi(r0, if_false);
+  Register map = r1;
+  Register type_reg = r2;
+  __ ldr(map, FieldMemOperand(r0, HeapObject::kMapOffset));
+  __ ldrb(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
+  __ sub(type_reg, type_reg, Operand(FIRST_SIMD_VALUE_TYPE));
+  __ cmp(type_reg, Operand(LAST_SIMD_VALUE_TYPE - FIRST_SIMD_VALUE_TYPE));
+  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+  Split(ls, if_true, if_false, fall_through);
+
+  context()->Plug(if_true, if_false);
+}
+
+
 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 1);
@@ -5076,6 +5103,30 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
     __ JumpIfSmi(r0, if_false);
     __ CompareObjectType(r0, r0, r1, FLOAT32X4_TYPE);
     Split(eq, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->int32x4_string())) {
+    __ JumpIfSmi(r0, if_false);
+    __ CompareObjectType(r0, r0, r1, INT32X4_TYPE);
+    Split(eq, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->bool32x4_string())) {
+    __ JumpIfSmi(r0, if_false);
+    __ CompareObjectType(r0, r0, r1, BOOL32X4_TYPE);
+    Split(eq, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->int16x8_string())) {
+    __ JumpIfSmi(r0, if_false);
+    __ CompareObjectType(r0, r0, r1, INT16X8_TYPE);
+    Split(eq, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->bool16x8_string())) {
+    __ JumpIfSmi(r0, if_false);
+    __ CompareObjectType(r0, r0, r1, BOOL16X8_TYPE);
+    Split(eq, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->int8x16_string())) {
+    __ JumpIfSmi(r0, if_false);
+    __ CompareObjectType(r0, r0, r1, INT8X16_TYPE);
+    Split(eq, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->bool8x16_string())) {
+    __ JumpIfSmi(r0, if_false);
+    __ CompareObjectType(r0, r0, r1, BOOL8X16_TYPE);
+    Split(eq, if_true, if_false, fall_through);
   } else if (String::Equals(check, factory->boolean_string())) {
     __ CompareRoot(r0, Heap::kTrueValueRootIndex);
     __ b(eq, if_true);
index 99cf863668a35b6c05cccd192da042e8e6c2b804..9944d32ef2c40b085dc29c887af7406219462d88 100644 (file)
@@ -3121,6 +3121,33 @@ void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitIsSimdObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK(args->length() == 1);
+
+  VisitForAccumulatorValue(args->at(0));
+
+  Label materialize_true, materialize_false;
+  Label* if_true = NULL;
+  Label* if_false = NULL;
+  Label* fall_through = NULL;
+  context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
+                         &if_false, &fall_through);
+
+  __ JumpIfSmi(x0, if_false);
+  Register map = x10;
+  Register type_reg = x11;
+  __ Ldr(map, FieldMemOperand(x0, HeapObject::kMapOffset));
+  __ Ldrb(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
+  __ Sub(type_reg, type_reg, Operand(FIRST_SIMD_VALUE_TYPE));
+  __ Cmp(type_reg, Operand(LAST_SIMD_VALUE_TYPE - FIRST_SIMD_VALUE_TYPE));
+  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+  Split(ls, if_true, if_false, fall_through);
+
+  context()->Plug(if_true, if_false);
+}
+
+
 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
   ASM_LOCATION("FullCodeGenerator::EmitIsUndetectableObject");
   ZoneList<Expression*>* args = expr->arguments();
@@ -4773,6 +4800,36 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
     __ JumpIfSmi(x0, if_false);
     __ CompareObjectType(x0, x0, x1, FLOAT32X4_TYPE);
     Split(eq, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->int32x4_string())) {
+    ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof int32x4_string");
+    __ JumpIfSmi(x0, if_false);
+    __ CompareObjectType(x0, x0, x1, INT32X4_TYPE);
+    Split(eq, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->bool32x4_string())) {
+    ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof bool32x4_string");
+    __ JumpIfSmi(x0, if_false);
+    __ CompareObjectType(x0, x0, x1, BOOL32X4_TYPE);
+    Split(eq, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->int16x8_string())) {
+    ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof int16x8_string");
+    __ JumpIfSmi(x0, if_false);
+    __ CompareObjectType(x0, x0, x1, INT16X8_TYPE);
+    Split(eq, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->bool16x8_string())) {
+    ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof bool16x8_string");
+    __ JumpIfSmi(x0, if_false);
+    __ CompareObjectType(x0, x0, x1, BOOL16X8_TYPE);
+    Split(eq, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->int8x16_string())) {
+    ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof int8x16_string");
+    __ JumpIfSmi(x0, if_false);
+    __ CompareObjectType(x0, x0, x1, INT8X16_TYPE);
+    Split(eq, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->bool8x16_string())) {
+    ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof bool8x16_string");
+    __ JumpIfSmi(x0, if_false);
+    __ CompareObjectType(x0, x0, x1, BOOL8X16_TYPE);
+    Split(eq, if_true, if_false, fall_through);
   } else if (String::Equals(check, factory->boolean_string())) {
     ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof boolean_string");
     __ JumpIfRoot(x0, Heap::kTrueValueRootIndex, if_true);
index d83712a563fd83d2a60eb89cb726d3b90a57a34e..c3ef66930e9a08284ee1e5c7ccf85cb06fb5ab62 100644 (file)
@@ -513,6 +513,7 @@ class FullCodeGenerator: public AstVisitor {
   F(IsFunction)                           \
   F(IsUndetectableObject)                 \
   F(IsSpecObject)                         \
+  F(IsSimdObject)                         \
   F(IsStringWrapperSafeForDefaultValueOf) \
   F(MathPow)                              \
   F(IsMinusZero)                          \
index 0d814d61827bd0172b1db62915f06e3bf1b1359c..94d22699aad3e7ed63d49e8b2b9759c579fc8f13 100644 (file)
@@ -3322,6 +3322,32 @@ void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitIsSimdObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK(args->length() == 1);
+
+  VisitForAccumulatorValue(args->at(0));
+
+  Label materialize_true, materialize_false;
+  Label* if_true = NULL;
+  Label* if_false = NULL;
+  Label* fall_through = NULL;
+  context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
+                         &if_false, &fall_through);
+
+  __ JumpIfSmi(eax, if_false);
+  Register map = ebx;
+  __ mov(map, FieldOperand(eax, HeapObject::kMapOffset));
+  __ CmpInstanceType(map, FIRST_SIMD_VALUE_TYPE);
+  __ j(less, if_false);
+  __ CmpInstanceType(map, LAST_SIMD_VALUE_TYPE);
+  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+  Split(less_equal, if_true, if_false, fall_through);
+
+  context()->Plug(if_true, if_false);
+}
+
+
 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 1);
@@ -5015,6 +5041,30 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
     __ JumpIfSmi(eax, if_false);
     __ CmpObjectType(eax, FLOAT32X4_TYPE, edx);
     Split(equal, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->int32x4_string())) {
+    __ JumpIfSmi(eax, if_false);
+    __ CmpObjectType(eax, INT32X4_TYPE, edx);
+    Split(equal, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->bool32x4_string())) {
+    __ JumpIfSmi(eax, if_false);
+    __ CmpObjectType(eax, BOOL32X4_TYPE, edx);
+    Split(equal, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->int16x8_string())) {
+    __ JumpIfSmi(eax, if_false);
+    __ CmpObjectType(eax, INT16X8_TYPE, edx);
+    Split(equal, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->bool16x8_string())) {
+    __ JumpIfSmi(eax, if_false);
+    __ CmpObjectType(eax, BOOL16X8_TYPE, edx);
+    Split(equal, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->int8x16_string())) {
+    __ JumpIfSmi(eax, if_false);
+    __ CmpObjectType(eax, INT8X16_TYPE, edx);
+    Split(equal, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->bool8x16_string())) {
+    __ JumpIfSmi(eax, if_false);
+    __ CmpObjectType(eax, BOOL8X16_TYPE, edx);
+    Split(equal, if_true, if_false, fall_through);
   } else if (String::Equals(check, factory->boolean_string())) {
     __ cmp(eax, isolate()->factory()->true_value());
     __ j(equal, if_true);
index 9e033e2d567e9e0321bb1137b5778a88c3315fd2..9fe4bbac1c3f2cc4996794b95fa28a7019803a6e 100644 (file)
@@ -3421,6 +3421,32 @@ void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitIsSimdObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK(args->length() == 1);
+
+  VisitForAccumulatorValue(args->at(0));
+
+  Label materialize_true, materialize_false;
+  Label* if_true = NULL;
+  Label* if_false = NULL;
+  Label* fall_through = NULL;
+  context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
+                         &if_false, &fall_through);
+
+  __ JumpIfSmi(v0, if_false);
+  Register map = a1;
+  Register type_reg = a2;
+  __ GetObjectType(v0, map, type_reg);
+  __ Subu(type_reg, type_reg, Operand(FIRST_SIMD_VALUE_TYPE));
+  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+  Split(ls, type_reg, Operand(LAST_SIMD_VALUE_TYPE - FIRST_SIMD_VALUE_TYPE),
+        if_true, if_false, fall_through);
+
+  context()->Plug(if_true, if_false);
+}
+
+
 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 1);
@@ -5107,6 +5133,30 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
     __ JumpIfSmi(v0, if_false);
     __ GetObjectType(v0, v0, a1);
     Split(eq, a1, Operand(FLOAT32X4_TYPE), if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->int32x4_string())) {
+    __ JumpIfSmi(v0, if_false);
+    __ GetObjectType(v0, v0, a1);
+    Split(eq, a1, Operand(INT32X4_TYPE), if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->bool32x4_string())) {
+    __ JumpIfSmi(v0, if_false);
+    __ GetObjectType(v0, v0, a1);
+    Split(eq, a1, Operand(BOOL32X4_TYPE), if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->int16x8_string())) {
+    __ JumpIfSmi(v0, if_false);
+    __ GetObjectType(v0, v0, a1);
+    Split(eq, a1, Operand(INT16X8_TYPE), if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->bool16x8_string())) {
+    __ JumpIfSmi(v0, if_false);
+    __ GetObjectType(v0, v0, a1);
+    Split(eq, a1, Operand(BOOL16X8_TYPE), if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->int8x16_string())) {
+    __ JumpIfSmi(v0, if_false);
+    __ GetObjectType(v0, v0, a1);
+    Split(eq, a1, Operand(INT8X16_TYPE), if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->bool8x16_string())) {
+    __ JumpIfSmi(v0, if_false);
+    __ GetObjectType(v0, v0, a1);
+    Split(eq, a1, Operand(BOOL8X16_TYPE), if_true, if_false, fall_through);
   } else if (String::Equals(check, factory->boolean_string())) {
     __ LoadRoot(at, Heap::kTrueValueRootIndex);
     __ Branch(if_true, eq, v0, Operand(at));
index a1d8950fec92d5dd430bb2e3523b3e96f209d70d..ac74e8d3eff7357b88d726357190d80a14920509 100644 (file)
@@ -3422,6 +3422,32 @@ void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitIsSimdObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK(args->length() == 1);
+
+  VisitForAccumulatorValue(args->at(0));
+
+  Label materialize_true, materialize_false;
+  Label* if_true = NULL;
+  Label* if_false = NULL;
+  Label* fall_through = NULL;
+  context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
+                         &if_false, &fall_through);
+
+  __ JumpIfSmi(v0, if_false);
+  Register map = a1;
+  Register type_reg = a2;
+  __ GetObjectType(v0, map, type_reg);
+  __ Subu(type_reg, type_reg, Operand(FIRST_SIMD_VALUE_TYPE));
+  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+  Split(ls, type_reg, Operand(LAST_SIMD_VALUE_TYPE - FIRST_SIMD_VALUE_TYPE),
+        if_true, if_false, fall_through);
+
+  context()->Plug(if_true, if_false);
+}
+
+
 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 1);
@@ -5109,6 +5135,30 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
     __ JumpIfSmi(v0, if_false);
     __ GetObjectType(v0, v0, a1);
     Split(eq, a1, Operand(FLOAT32X4_TYPE), if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->int32x4_string())) {
+    __ JumpIfSmi(v0, if_false);
+    __ GetObjectType(v0, v0, a1);
+    Split(eq, a1, Operand(INT32X4_TYPE), if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->bool32x4_string())) {
+    __ JumpIfSmi(v0, if_false);
+    __ GetObjectType(v0, v0, a1);
+    Split(eq, a1, Operand(BOOL32X4_TYPE), if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->int16x8_string())) {
+    __ JumpIfSmi(v0, if_false);
+    __ GetObjectType(v0, v0, a1);
+    Split(eq, a1, Operand(INT16X8_TYPE), if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->bool16x8_string())) {
+    __ JumpIfSmi(v0, if_false);
+    __ GetObjectType(v0, v0, a1);
+    Split(eq, a1, Operand(BOOL16X8_TYPE), if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->int8x16_string())) {
+    __ JumpIfSmi(v0, if_false);
+    __ GetObjectType(v0, v0, a1);
+    Split(eq, a1, Operand(INT8X16_TYPE), if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->bool8x16_string())) {
+    __ JumpIfSmi(v0, if_false);
+    __ GetObjectType(v0, v0, a1);
+    Split(eq, a1, Operand(BOOL8X16_TYPE), if_true, if_false, fall_through);
   } else if (String::Equals(check, factory->boolean_string())) {
     __ LoadRoot(at, Heap::kTrueValueRootIndex);
     __ Branch(if_true, eq, v0, Operand(at));
index 7234e6abf98751456fdf15e1d689bd42719facf5..9c5c8f32dbe62dbde725dfbd6136e4d80f76bb24 100644 (file)
@@ -3423,6 +3423,33 @@ void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitIsSimdObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK(args->length() == 1);
+
+  VisitForAccumulatorValue(args->at(0));
+
+  Label materialize_true, materialize_false;
+  Label* if_true = NULL;
+  Label* if_false = NULL;
+  Label* fall_through = NULL;
+  context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
+                         &if_false, &fall_through);
+
+  __ JumpIfSmi(r3, if_false);
+  Register map = r4;
+  Register type_reg = r5;
+  __ LoadP(map, FieldMemOperand(r3, HeapObject::kMapOffset));
+  __ lbz(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
+  __ subi(type_reg, type_reg, Operand(FIRST_SIMD_VALUE_TYPE));
+  __ cmpli(type_reg, Operand(LAST_SIMD_VALUE_TYPE - FIRST_SIMD_VALUE_TYPE));
+  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+  Split(le, if_true, if_false, fall_through);
+
+  context()->Plug(if_true, if_false);
+}
+
+
 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 1);
@@ -5096,6 +5123,30 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
     __ JumpIfSmi(r3, if_false);
     __ CompareObjectType(r3, r3, r4, FLOAT32X4_TYPE);
     Split(eq, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->int32x4_string())) {
+    __ JumpIfSmi(r3, if_false);
+    __ CompareObjectType(r3, r3, r4, INT32X4_TYPE);
+    Split(eq, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->bool32x4_string())) {
+    __ JumpIfSmi(r3, if_false);
+    __ CompareObjectType(r3, r3, r4, BOOL32X4_TYPE);
+    Split(eq, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->int16x8_string())) {
+    __ JumpIfSmi(r3, if_false);
+    __ CompareObjectType(r3, r3, r4, INT16X8_TYPE);
+    Split(eq, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->bool16x8_string())) {
+    __ JumpIfSmi(r3, if_false);
+    __ CompareObjectType(r3, r3, r4, BOOL16X8_TYPE);
+    Split(eq, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->int8x16_string())) {
+    __ JumpIfSmi(r3, if_false);
+    __ CompareObjectType(r3, r3, r4, INT8X16_TYPE);
+    Split(eq, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->bool8x16_string())) {
+    __ JumpIfSmi(r3, if_false);
+    __ CompareObjectType(r3, r3, r4, BOOL8X16_TYPE);
+    Split(eq, if_true, if_false, fall_through);
   } else if (String::Equals(check, factory->boolean_string())) {
     __ CompareRoot(r3, Heap::kTrueValueRootIndex);
     __ beq(if_true);
index 377bf67ee71740d51a2dbae04431409302afe8ce..b5dc54eea0e0beb33d8484d0570f7fe40c487a36 100644 (file)
@@ -3315,6 +3315,32 @@ void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitIsSimdObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK(args->length() == 1);
+
+  VisitForAccumulatorValue(args->at(0));
+
+  Label materialize_true, materialize_false;
+  Label* if_true = NULL;
+  Label* if_false = NULL;
+  Label* fall_through = NULL;
+  context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
+                         &if_false, &fall_through);
+
+  __ JumpIfSmi(rax, if_false);
+  Register map = rbx;
+  __ movp(map, FieldOperand(rax, HeapObject::kMapOffset));
+  __ CmpInstanceType(map, FIRST_SIMD_VALUE_TYPE);
+  __ j(less, if_false);
+  __ CmpInstanceType(map, LAST_SIMD_VALUE_TYPE);
+  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+  Split(less_equal, if_true, if_false, fall_through);
+
+  context()->Plug(if_true, if_false);
+}
+
+
 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 1);
@@ -5033,6 +5059,30 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
     __ JumpIfSmi(rax, if_false);
     __ CmpObjectType(rax, FLOAT32X4_TYPE, rdx);
     Split(equal, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->int32x4_string())) {
+    __ JumpIfSmi(rax, if_false);
+    __ CmpObjectType(rax, INT32X4_TYPE, rdx);
+    Split(equal, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->bool32x4_string())) {
+    __ JumpIfSmi(rax, if_false);
+    __ CmpObjectType(rax, BOOL32X4_TYPE, rdx);
+    Split(equal, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->int16x8_string())) {
+    __ JumpIfSmi(rax, if_false);
+    __ CmpObjectType(rax, INT16X8_TYPE, rdx);
+    Split(equal, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->bool16x8_string())) {
+    __ JumpIfSmi(rax, if_false);
+    __ CmpObjectType(rax, BOOL16X8_TYPE, rdx);
+    Split(equal, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->int8x16_string())) {
+    __ JumpIfSmi(rax, if_false);
+    __ CmpObjectType(rax, INT8X16_TYPE, rdx);
+    Split(equal, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->bool8x16_string())) {
+    __ JumpIfSmi(rax, if_false);
+    __ CmpObjectType(rax, BOOL8X16_TYPE, rdx);
+    Split(equal, if_true, if_false, fall_through);
   } else if (String::Equals(check, factory->boolean_string())) {
     __ CompareRoot(rax, Heap::kTrueValueRootIndex);
     __ j(equal, if_true);
index dbe28ae75d0f57428caf3e8fb473af6396bd4872..198f8616d3a521539069c44726a121e4c8f119ba 100644 (file)
@@ -3313,6 +3313,32 @@ void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK(args->length() == 1);
+
+  VisitForAccumulatorValue(args->at(0));
+
+  Label materialize_true, materialize_false;
+  Label* if_true = NULL;
+  Label* if_false = NULL;
+  Label* fall_through = NULL;
+  context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
+                         &if_false, &fall_through);
+
+  __ JumpIfSmi(eax, if_false);
+  Register map = ebx;
+  __ mov(map, FieldOperand(eax, HeapObject::kMapOffset));
+  __ CmpInstanceType(map, FIRST_SIMD_VALUE_TYPE);
+  __ j(less, if_false);
+  __ CmpInstanceType(map, LAST_SIMD_VALUE_TYPE);
+  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
+  Split(less_equal, if_true, if_false, fall_through);
+
+  context()->Plug(if_true, if_false);
+}
+
+
 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 1);
@@ -5006,6 +5032,30 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
     __ JumpIfSmi(eax, if_false);
     __ CmpObjectType(eax, FLOAT32X4_TYPE, edx);
     Split(equal, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->int32x4_string())) {
+    __ JumpIfSmi(eax, if_false);
+    __ CmpObjectType(eax, INT32X4_TYPE, edx);
+    Split(equal, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->bool32x4_string())) {
+    __ JumpIfSmi(eax, if_false);
+    __ CmpObjectType(eax, BOOL32X4_TYPE, edx);
+    Split(equal, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->int16x8_string())) {
+    __ JumpIfSmi(eax, if_false);
+    __ CmpObjectType(eax, INT16X8_TYPE, edx);
+    Split(equal, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->bool16x8_string())) {
+    __ JumpIfSmi(eax, if_false);
+    __ CmpObjectType(eax, BOOL16X8_TYPE, edx);
+    Split(equal, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->int8x16_string())) {
+    __ JumpIfSmi(eax, if_false);
+    __ CmpObjectType(eax, INT8X16_TYPE, edx);
+    Split(equal, if_true, if_false, fall_through);
+  } else if (String::Equals(check, factory->bool8x16_string())) {
+    __ JumpIfSmi(eax, if_false);
+    __ CmpObjectType(eax, BOOL8X16_TYPE, edx);
+    Split(equal, if_true, if_false, fall_through);
   } else if (String::Equals(check, factory->boolean_string())) {
     __ cmp(eax, isolate()->factory()->true_value());
     __ j(equal, if_true);
index a4378167dacdbb5e3729ad7ad53d6bfad8a19a9d..5119adc9296fc51f452d168f5d79133f4cd6ab74 100644 (file)
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-var $float32x4ToString;
-
 (function(global, utils) {
 
 "use strict";
@@ -14,90 +12,276 @@ var $float32x4ToString;
 // Imports
 
 var GlobalSIMD = global.SIMD;
-var GlobalFloat32x4 = GlobalSIMD.Float32x4;
 
-//-------------------------------------------------------------------
+macro SIMD_TYPES(FUNCTION)
+FUNCTION(Float32x4, float32x4, 4)
+FUNCTION(Int32x4, int32x4, 4)
+FUNCTION(Bool32x4, bool32x4, 4)
+FUNCTION(Int16x8, int16x8, 8)
+FUNCTION(Bool16x8, bool16x8, 8)
+FUNCTION(Int8x16, int8x16, 16)
+FUNCTION(Bool8x16, bool8x16, 16)
+endmacro
 
-function Float32x4Constructor(x, y, z, w) {
-  if (%_IsConstructCall()) throw MakeTypeError(kNotConstructor, "Float32x4");
-  if (!IS_NUMBER(x) || !IS_NUMBER(y) || !IS_NUMBER(z) || !IS_NUMBER(w)) {
-    throw MakeTypeError(kInvalidArgument);
-  }
-  return %CreateFloat32x4(x, y, z, w);
-}
+macro DECLARE_GLOBALS(NAME, TYPE, LANES)
+var GlobalNAME = GlobalSIMD.NAME;
+endmacro
 
-function Float32x4Splat(s) {
-  return %CreateFloat32x4(s, s, s, s);
-}
+SIMD_TYPES(DECLARE_GLOBALS)
 
-function Float32x4CheckJS(a) {
-  return %Float32x4Check(a);
+macro DECLARE_COMMON_FUNCTIONS(NAME, TYPE, LANES)
+function NAMECheckJS(a) {
+  return %NAMECheck(a);
 }
 
-function Float32x4ToString() {
-  if (!(IS_FLOAT32X4(this) || IS_FLOAT32X4_WRAPPER(this))) {
+function NAMEToString() {
+  if (typeof(this) !== 'TYPE' && %_ClassOf(this) !== 'NAME') {
     throw MakeTypeError(kIncompatibleMethodReceiver,
-                        "Float32x4.prototype.toString", this);
+                        "NAME.prototype.toString", this);
   }
   var value = %_ValueOf(this);
-  var w = GlobalFloat32x4.extractLane(value, 0),
-      x = GlobalFloat32x4.extractLane(value, 1),
-      y = GlobalFloat32x4.extractLane(value, 2),
-      z = GlobalFloat32x4.extractLane(value, 3);
-  return "SIMD.Float32x4(" + w + ", " + x + ", " + y + ", " + z + ")";
+  var str = "SIMD.NAME(";
+  str += %NAMEExtractLane(value, 0);
+  for (var i = 1; i < LANES; i++) {
+    str += ", " + %NAMEExtractLane(value, i);
+  }
+  return str + ")";
 }
 
-function Float32x4ToLocaleString() {
-  if (!(IS_FLOAT32X4(this) || IS_FLOAT32X4_WRAPPER(this))) {
+function NAMEToLocaleString() {
+  if (typeof(this) !== 'TYPE' && %_ClassOf(this) !== 'NAME') {
     throw MakeTypeError(kIncompatibleMethodReceiver,
-                        "Float32x4.prototype.toLocaleString", this);
+                        "NAME.prototype.toLocaleString", this);
   }
   var value = %_ValueOf(this);
-  var w = GlobalFloat32x4.extractLane(value, 0).toLocaleString(),
-      x = GlobalFloat32x4.extractLane(value, 1).toLocaleString(),
-      y = GlobalFloat32x4.extractLane(value, 2).toLocaleString(),
-      z = GlobalFloat32x4.extractLane(value, 3).toLocaleString();
-  return "SIMD.Float32x4(" + w + ", " + x + ", " + y + ", " + z + ")";
+  var str = "SIMD.NAME(";
+  str += %NAMEExtractLane(value, 0).toLocaleString();
+  for (var i = 1; i < LANES; i++) {
+    str += ", " + %NAMEExtractLane(value, i).toLocaleString();
+  }
+  return str + ")";
 }
 
-function Float32x4ValueOf() {
-  if (!(IS_FLOAT32X4(this) || IS_FLOAT32X4_WRAPPER(this))) {
+function NAMEValueOf() {
+  if (typeof(this) !== 'TYPE' && %_ClassOf(this) !== 'NAME') {
     throw MakeTypeError(kIncompatibleMethodReceiver,
-                        "Float32x4.prototype.valueOf", this);
+                        "NAME.prototype.valueOf", this);
   }
   return %_ValueOf(this);
 }
 
+function NAMEExtractLaneJS(instance, lane) {
+  return %NAMEExtractLane(instance, lane);
+}
+endmacro
+
+SIMD_TYPES(DECLARE_COMMON_FUNCTIONS)
+
+macro SIMD_NUMERIC_TYPES(FUNCTION)
+FUNCTION(Float32x4)
+FUNCTION(Int32x4)
+FUNCTION(Int16x8)
+FUNCTION(Int8x16)
+endmacro
+
+macro DECLARE_NUMERIC_FUNCTIONS(NAME)
+function NAMEReplaceLaneJS(instance, lane, value) {
+  return %NAMEReplaceLane(instance, lane, TO_NUMBER_INLINE(value));
+}
+endmacro
+
+SIMD_NUMERIC_TYPES(DECLARE_NUMERIC_FUNCTIONS)
+
+macro SIMD_BOOL_TYPES(FUNCTION)
+FUNCTION(Bool32x4)
+FUNCTION(Bool16x8)
+FUNCTION(Bool8x16)
+endmacro
+
+macro DECLARE_BOOL_FUNCTIONS(NAME)
+function NAMEReplaceLaneJS(instance, lane, value) {
+  return %NAMEReplaceLane(instance, lane, value);
+}
+endmacro
+
+SIMD_BOOL_TYPES(DECLARE_BOOL_FUNCTIONS)
+
+macro SIMD_UNSIGNED_INT_TYPES(FUNCTION)
+FUNCTION(Int16x8)
+FUNCTION(Int8x16)
+endmacro
+
+macro DECLARE_UNSIGNED_INT_FUNCTIONS(NAME)
+function NAMEUnsignedExtractLaneJS(instance, lane) {
+  return %NAMEUnsignedExtractLane(instance, lane);
+}
+endmacro
+
+SIMD_UNSIGNED_INT_TYPES(DECLARE_UNSIGNED_INT_FUNCTIONS)
+
 //-------------------------------------------------------------------
 
-function Float32x4ExtractLaneJS(value, lane) {
-  return %Float32x4ExtractLane(value, lane);
+function Float32x4Constructor(c0, c1, c2, c3) {
+  if (%_IsConstructCall()) throw MakeTypeError(kNotConstructor, "Float32x4");
+  return %CreateFloat32x4(TO_NUMBER_INLINE(c0), TO_NUMBER_INLINE(c1),
+                          TO_NUMBER_INLINE(c2), TO_NUMBER_INLINE(c3));
+}
+
+
+function Float32x4Splat(s) {
+  return %CreateFloat32x4(s, s, s, s);
+}
+
+
+function Int32x4Constructor(c0, c1, c2, c3) {
+  if (%_IsConstructCall()) throw MakeTypeError(kNotConstructor, "Int32x4");
+  return %CreateInt32x4(TO_NUMBER_INLINE(c0), TO_NUMBER_INLINE(c1),
+                        TO_NUMBER_INLINE(c2), TO_NUMBER_INLINE(c3));
+}
+
+
+function Int32x4Splat(s) {
+  return %CreateInt32x4(s, s, s, s);
+}
+
+
+function Bool32x4Constructor(c0, c1, c2, c3) {
+  if (%_IsConstructCall()) throw MakeTypeError(kNotConstructor, "Bool32x4");
+  return %CreateBool32x4(c0, c1, c2, c3);
+}
+
+
+function Bool32x4Splat(s) {
+  return %CreateBool32x4(s, s, s, s);
+}
+
+
+function Int16x8Constructor(c0, c1, c2, c3, c4, c5, c6, c7) {
+  if (%_IsConstructCall()) throw MakeTypeError(kNotConstructor, "Int16x8");
+  return %CreateInt16x8(TO_NUMBER_INLINE(c0), TO_NUMBER_INLINE(c1),
+                        TO_NUMBER_INLINE(c2), TO_NUMBER_INLINE(c3),
+                        TO_NUMBER_INLINE(c4), TO_NUMBER_INLINE(c5),
+                        TO_NUMBER_INLINE(c6), TO_NUMBER_INLINE(c7));
+}
+
+
+function Int16x8Splat(s) {
+  return %CreateInt16x8(s, s, s, s, s, s, s, s);
+}
+
+
+function Bool16x8Constructor(c0, c1, c2, c3, c4, c5, c6, c7) {
+  if (%_IsConstructCall()) throw MakeTypeError(kNotConstructor, "Bool16x8");
+  return %CreateBool16x8(c0, c1, c2, c3, c4, c5, c6, c7);
+}
+
+
+function Bool16x8Splat(s) {
+  return %CreateBool16x8(s, s, s, s, s, s, s, s);
+}
+
+
+function Int8x16Constructor(c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11,
+                            c12, c13, c14, c15) {
+  if (%_IsConstructCall()) throw MakeTypeError(kNotConstructor, "Int8x16");
+  return %CreateInt8x16(TO_NUMBER_INLINE(c0), TO_NUMBER_INLINE(c1),
+                        TO_NUMBER_INLINE(c2), TO_NUMBER_INLINE(c3),
+                        TO_NUMBER_INLINE(c4), TO_NUMBER_INLINE(c5),
+                        TO_NUMBER_INLINE(c6), TO_NUMBER_INLINE(c7),
+                        TO_NUMBER_INLINE(c8), TO_NUMBER_INLINE(c9),
+                        TO_NUMBER_INLINE(c10), TO_NUMBER_INLINE(c11),
+                        TO_NUMBER_INLINE(c12), TO_NUMBER_INLINE(c13),
+                        TO_NUMBER_INLINE(c14), TO_NUMBER_INLINE(c15));
+}
+
+
+function Int8x16Splat(s) {
+  return %CreateInt8x16(s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s);
+}
+
+
+function Bool8x16Constructor(c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11,
+                             c12, c13, c14, c15) {
+  if (%_IsConstructCall()) throw MakeTypeError(kNotConstructor, "Bool8x16");
+  return %CreateBool8x16(c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
+                         c13, c14, c15);
+}
+
+
+function Bool8x16Splat(s) {
+  return %CreateBool8x16(s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s);
 }
 
-// -------------------------------------------------------------------
 
 %AddNamedProperty(GlobalSIMD, symbolToStringTag, 'SIMD', READ_ONLY | DONT_ENUM);
 
-%SetCode(GlobalFloat32x4, Float32x4Constructor);
-%FunctionSetPrototype(GlobalFloat32x4, {});
-%AddNamedProperty(
-    GlobalFloat32x4.prototype, 'constructor', GlobalFloat32x4, DONT_ENUM);
-%AddNamedProperty(
-    GlobalFloat32x4.prototype, symbolToStringTag, 'Float32x4',
+macro SETUP_SIMD_TYPE(NAME, TYPE, LANES)
+%SetCode(GlobalNAME, NAMEConstructor);
+%FunctionSetPrototype(GlobalNAME, {});
+%AddNamedProperty(GlobalNAME.prototype, 'constructor', GlobalNAME,
+    DONT_ENUM);
+%AddNamedProperty(GlobalNAME.prototype, symbolToStringTag, 'NAME',
     DONT_ENUM | READ_ONLY);
-
-utils.InstallFunctions(GlobalFloat32x4.prototype, DONT_ENUM, [
-  'toLocaleString', Float32x4ToLocaleString,
-  'toString', Float32x4ToString,
-  'valueOf', Float32x4ValueOf,
+utils.InstallFunctions(GlobalNAME.prototype, DONT_ENUM, [
+  'toLocaleString', NAMEToLocaleString,
+  'toString', NAMEToString,
+  'valueOf', NAMEValueOf,
 ]);
+endmacro
+
+SIMD_TYPES(SETUP_SIMD_TYPE)
+
+//-------------------------------------------------------------------
 
 utils.InstallFunctions(GlobalFloat32x4, DONT_ENUM, [
   'splat', Float32x4Splat,
   'check', Float32x4CheckJS,
   'extractLane', Float32x4ExtractLaneJS,
+  'replaceLane', Float32x4ReplaceLaneJS,
+]);
+
+utils.InstallFunctions(GlobalInt32x4, DONT_ENUM, [
+  'splat', Int32x4Splat,
+  'check', Int32x4CheckJS,
+  'extractLane', Int32x4ExtractLaneJS,
+  'replaceLane', Int32x4ReplaceLaneJS,
+]);
+
+utils.InstallFunctions(GlobalBool32x4, DONT_ENUM, [
+  'splat', Bool32x4Splat,
+  'check', Bool32x4CheckJS,
+  'extractLane', Bool32x4ExtractLaneJS,
+  'replaceLane', Bool32x4ReplaceLaneJS,
+]);
+
+utils.InstallFunctions(GlobalInt16x8, DONT_ENUM, [
+  'splat', Int16x8Splat,
+  'check', Int16x8CheckJS,
+  'extractLane', Int16x8ExtractLaneJS,
+  'unsignedExtractLane', Int16x8UnsignedExtractLaneJS,
+  'replaceLane', Int16x8ReplaceLaneJS,
 ]);
 
-$float32x4ToString = Float32x4ToString;
+utils.InstallFunctions(GlobalBool16x8, DONT_ENUM, [
+  'splat', Bool16x8Splat,
+  'check', Bool16x8CheckJS,
+  'extractLane', Bool16x8ExtractLaneJS,
+  'replaceLane', Bool16x8ReplaceLaneJS,
+]);
+
+utils.InstallFunctions(GlobalInt8x16, DONT_ENUM, [
+  'splat', Int8x16Splat,
+  'check', Int8x16CheckJS,
+  'extractLane', Int8x16ExtractLaneJS,
+  'unsignedExtractLane', Int8x16UnsignedExtractLaneJS,
+  'replaceLane', Int8x16ReplaceLaneJS,
+]);
+
+utils.InstallFunctions(GlobalBool8x16, DONT_ENUM, [
+  'splat', Bool8x16Splat,
+  'check', Bool8x16CheckJS,
+  'extractLane', Bool8x16ExtractLaneJS,
+  'replaceLane', Bool8x16ReplaceLaneJS,
+]);
 
 })
index 693361ce0443486891798f1caca4b9e4d8440ba6..a4c3f1147e6ce6cea5dc90cead74d46d249edf6c 100644 (file)
@@ -861,7 +861,7 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) {
     return AddEntry(object, HeapEntry::kArray, "");
   } else if (object->IsHeapNumber()) {
     return AddEntry(object, HeapEntry::kHeapNumber, "number");
-  } else if (object->IsFloat32x4()) {
+  } else if (object->IsSimd128Value()) {
     return AddEntry(object, HeapEntry::kSimdValue, "simd");
   }
   return AddEntry(object, HeapEntry::kHidden, GetSystemEntryName(object));
index dc82f8a78ae1a634a1790fc84727290ddd97a332..4f5a064cca37a0f51ce644a815da5786008d664a 100644 (file)
@@ -2974,6 +2974,12 @@ bool Heap::CreateInitialMaps() {
     ALLOCATE_MAP(MUTABLE_HEAP_NUMBER_TYPE, HeapNumber::kSize,
                  mutable_heap_number)
     ALLOCATE_MAP(FLOAT32X4_TYPE, Float32x4::kSize, float32x4)
+    ALLOCATE_MAP(INT32X4_TYPE, Int32x4::kSize, int32x4)
+    ALLOCATE_MAP(BOOL32X4_TYPE, Bool32x4::kSize, bool32x4)
+    ALLOCATE_MAP(INT16X8_TYPE, Int16x8::kSize, int16x8)
+    ALLOCATE_MAP(BOOL16X8_TYPE, Bool16x8::kSize, bool16x8)
+    ALLOCATE_MAP(INT8X16_TYPE, Int8x16::kSize, int8x16)
+    ALLOCATE_MAP(BOOL8X16_TYPE, Bool8x16::kSize, bool8x16)
     ALLOCATE_MAP(SYMBOL_TYPE, Symbol::kSize, symbol)
     ALLOCATE_MAP(FOREIGN_TYPE, Foreign::kSize, foreign)
 
@@ -3113,31 +3119,30 @@ AllocationResult Heap::AllocateHeapNumber(double value, MutableMode mode,
   return result;
 }
 
-
-AllocationResult Heap::AllocateFloat32x4(float w, float x, float y, float z,
-                                         PretenureFlag pretenure) {
-  // Statically ensure that it is safe to allocate SIMD values in paged
-  // spaces.
-  int size = Float32x4::kSize;
-  STATIC_ASSERT(Float32x4::kSize <= Page::kMaxRegularHeapObjectSize);
-
-  AllocationSpace space = SelectSpace(size, pretenure);
-
-  HeapObject* result;
-  {
-    AllocationResult allocation =
-        AllocateRaw(size, space, OLD_SPACE, kSimd128Unaligned);
-    if (!allocation.To(&result)) return allocation;
-  }
-
-  result->set_map_no_write_barrier(float32x4_map());
-  Float32x4* float32x4 = Float32x4::cast(result);
-  float32x4->set_lane(0, w);
-  float32x4->set_lane(1, x);
-  float32x4->set_lane(2, y);
-  float32x4->set_lane(3, z);
-  return result;
-}
+#define SIMD_ALLOCATE_DEFINITION(type, type_name, lane_count, lane_type) \
+  AllocationResult Heap::Allocate##type(lane_type lanes[lane_count],     \
+                                        PretenureFlag pretenure) {       \
+    int size = type::kSize;                                              \
+    STATIC_ASSERT(type::kSize <= Page::kMaxRegularHeapObjectSize);       \
+                                                                         \
+    AllocationSpace space = SelectSpace(size, pretenure);                \
+                                                                         \
+    HeapObject* result;                                                  \
+    {                                                                    \
+      AllocationResult allocation =                                      \
+          AllocateRaw(size, space, OLD_SPACE, kSimd128Unaligned);        \
+      if (!allocation.To(&result)) return allocation;                    \
+    }                                                                    \
+                                                                         \
+    result->set_map_no_write_barrier(type_name##_map());                 \
+    type* instance = type::cast(result);                                 \
+    for (int i = 0; i < lane_count; i++) {                               \
+      instance->set_lane(i, lanes[i]);                                   \
+    }                                                                    \
+    return result;                                                       \
+  }
+
+SIMD128_TYPES(SIMD_ALLOCATE_DEFINITION)
 
 
 AllocationResult Heap::AllocateCell(Object* value) {
index 17e4074b117d00e856334b26bcbe166573ce87d8..089fe7878c7a2baf6fc279d9e54c30aff2c4d6e8 100644 (file)
@@ -48,6 +48,12 @@ namespace internal {
   V(Map, heap_number_map, HeapNumberMap)                                       \
   V(Map, mutable_heap_number_map, MutableHeapNumberMap)                        \
   V(Map, float32x4_map, Float32x4Map)                                          \
+  V(Map, int32x4_map, Int32x4Map)                                              \
+  V(Map, bool32x4_map, Bool32x4Map)                                            \
+  V(Map, int16x8_map, Int16x8Map)                                              \
+  V(Map, bool16x8_map, Bool16x8Map)                                            \
+  V(Map, int8x16_map, Int8x16Map)                                              \
+  V(Map, bool8x16_map, Bool8x16Map)                                            \
   V(Map, native_context_map, NativeContextMap)                                 \
   V(Map, fixed_array_map, FixedArrayMap)                                       \
   V(Map, code_map, CodeMap)                                                    \
@@ -213,6 +219,18 @@ namespace internal {
   V(eval_string, "eval")                                       \
   V(float32x4_string, "float32x4")                             \
   V(Float32x4_string, "Float32x4")                             \
+  V(int32x4_string, "int32x4")                                 \
+  V(Int32x4_string, "Int32x4")                                 \
+  V(bool32x4_string, "bool32x4")                               \
+  V(Bool32x4_string, "Bool32x4")                               \
+  V(int16x8_string, "int16x8")                                 \
+  V(Int16x8_string, "Int16x8")                                 \
+  V(bool16x8_string, "bool16x8")                               \
+  V(Bool16x8_string, "Bool16x8")                               \
+  V(int8x16_string, "int8x16")                                 \
+  V(Int8x16_string, "Int8x16")                                 \
+  V(bool8x16_string, "bool8x16")                               \
+  V(Bool8x16_string, "Bool8x16")                               \
   V(function_string, "function")                               \
   V(Function_string, "Function")                               \
   V(length_string, "length")                                   \
@@ -338,6 +356,12 @@ namespace internal {
   V(HeapNumberMap)                      \
   V(MutableHeapNumberMap)               \
   V(Float32x4Map)                       \
+  V(Int32x4Map)                         \
+  V(Bool32x4Map)                        \
+  V(Int16x8Map)                         \
+  V(Bool16x8Map)                        \
+  V(Int8x16Map)                         \
+  V(Bool8x16Map)                        \
   V(NativeContextMap)                   \
   V(FixedArrayMap)                      \
   V(CodeMap)                            \
@@ -1647,10 +1671,12 @@ class Heap {
       AllocateHeapNumber(double value, MutableMode mode = IMMUTABLE,
                          PretenureFlag pretenure = NOT_TENURED);
 
-  // Allocates a Float32x4 from the given lane values.
-  MUST_USE_RESULT AllocationResult
-  AllocateFloat32x4(float w, float x, float y, float z,
-                    PretenureFlag pretenure = NOT_TENURED);
+// Allocates SIMD values from the given lane values.
+#define SIMD_ALLOCATE_DECLARATION(type, type_name, lane_count, lane_type) \
+  AllocationResult Allocate##type(lane_type lanes[lane_count],            \
+                                  PretenureFlag pretenure = NOT_TENURED);
+
+  SIMD128_TYPES(SIMD_ALLOCATE_DECLARATION)
 
   // Allocates a byte array of the specified length
   MUST_USE_RESULT AllocationResult
index 70f26a504a7f743de883094653103b9158fd4344..0e2cba0e2f6cf951c4f85c2ea57a17387ba69e98 100644 (file)
@@ -139,6 +139,12 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId(
     case HEAP_NUMBER_TYPE:
     case MUTABLE_HEAP_NUMBER_TYPE:
     case FLOAT32X4_TYPE:
+    case INT32X4_TYPE:
+    case BOOL32X4_TYPE:
+    case INT16X8_TYPE:
+    case BOOL16X8_TYPE:
+    case INT8X16_TYPE:
+    case BOOL8X16_TYPE:
       return GetVisitorIdForSize(kVisitDataObject, kVisitDataObjectGeneric,
                                  instance_size, has_unboxed_fields);
 
index 2586da9be135a94f1c63bab65b12da1ae568ef56..2e9475542b8b56e5c7c6c54e4ca83aa578aac380 100644 (file)
@@ -1328,6 +1328,18 @@ static String* TypeOfString(HConstant* constant, Isolate* isolate) {
       return heap->symbol_string();
     case FLOAT32X4_TYPE:
       return heap->float32x4_string();
+    case INT32X4_TYPE:
+      return heap->int32x4_string();
+    case BOOL32X4_TYPE:
+      return heap->bool32x4_string();
+    case INT16X8_TYPE:
+      return heap->int16x8_string();
+    case BOOL16X8_TYPE:
+      return heap->bool16x8_string();
+    case INT8X16_TYPE:
+      return heap->int8x16_string();
+    case BOOL8X16_TYPE:
+      return heap->bool8x16_string();
     case JS_FUNCTION_TYPE:
     case JS_FUNCTION_PROXY_TYPE:
       return heap->function_string();
index bf2630b94474f1f06ce0a63654f6a6fd13122ab6..026a310b08fb626e171cd4efd6887b4604d3153a 100644 (file)
@@ -1694,6 +1694,7 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
            Immediate(isolate()->factory()->heap_number_map()));
     __ j(equal, &generic_heap_number_comparison, Label::kNear);
     if (cc != equal) {
+      Label not_simd;
       __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
       __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
       // Call runtime on identical JSObjects.  Otherwise return equal.
@@ -1703,8 +1704,11 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
       __ cmpb(ecx, static_cast<uint8_t>(SYMBOL_TYPE));
       __ j(equal, &runtime_call, Label::kFar);
       // Call runtime on identical SIMD values since we must throw a TypeError.
-      __ cmpb(ecx, static_cast<uint8_t>(FLOAT32X4_TYPE));
-      __ j(equal, &runtime_call, Label::kFar);
+      __ cmpb(ecx, static_cast<uint8_t>(FIRST_SIMD_VALUE_TYPE));
+      __ j(less, &not_simd, Label::kFar);
+      __ cmpb(ecx, static_cast<uint8_t>(LAST_SIMD_VALUE_TYPE));
+      __ j(less_equal, &runtime_call, Label::kFar);
+      __ bind(&not_simd);
       if (is_strong(strength())) {
         // We have already tested for smis and heap numbers, so if both
         // arguments are not strings we must proceed to the slow case.
index 8b528d15206191c45a60b85a77fc780614ed118c..ab3426ed9ce5f93f3d79252f1751aec75f9610bc 100644 (file)
@@ -2170,8 +2170,12 @@ void LCodeGen::DoBranch(LBranch* instr) {
 
       if (expected.Contains(ToBooleanStub::SIMD_VALUE)) {
         // SIMD value -> true.
-        __ CmpInstanceType(map, FLOAT32X4_TYPE);
-        __ j(equal, instr->TrueLabel(chunk_));
+        Label not_simd;
+        __ CmpInstanceType(map, FIRST_SIMD_VALUE_TYPE);
+        __ j(less, &not_simd, Label::kNear);
+        __ CmpInstanceType(map, LAST_SIMD_VALUE_TYPE);
+        __ j(less_equal, instr->TrueLabel(chunk_));
+        __ bind(&not_simd);
       }
 
       if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
@@ -5544,6 +5548,36 @@ Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
     __ CmpObjectType(input, FLOAT32X4_TYPE, input);
     final_branch_condition = equal;
 
+  } else if (String::Equals(type_name, factory()->int32x4_string())) {
+    __ JumpIfSmi(input, false_label, false_distance);
+    __ CmpObjectType(input, INT32X4_TYPE, input);
+    final_branch_condition = equal;
+
+  } else if (String::Equals(type_name, factory()->bool32x4_string())) {
+    __ JumpIfSmi(input, false_label, false_distance);
+    __ CmpObjectType(input, BOOL32X4_TYPE, input);
+    final_branch_condition = equal;
+
+  } else if (String::Equals(type_name, factory()->int16x8_string())) {
+    __ JumpIfSmi(input, false_label, false_distance);
+    __ CmpObjectType(input, INT16X8_TYPE, input);
+    final_branch_condition = equal;
+
+  } else if (String::Equals(type_name, factory()->bool16x8_string())) {
+    __ JumpIfSmi(input, false_label, false_distance);
+    __ CmpObjectType(input, BOOL16X8_TYPE, input);
+    final_branch_condition = equal;
+
+  } else if (String::Equals(type_name, factory()->int8x16_string())) {
+    __ JumpIfSmi(input, false_label, false_distance);
+    __ CmpObjectType(input, INT8X16_TYPE, input);
+    final_branch_condition = equal;
+
+  } else if (String::Equals(type_name, factory()->bool8x16_string())) {
+    __ JumpIfSmi(input, false_label, false_distance);
+    __ CmpObjectType(input, BOOL8X16_TYPE, input);
+    final_branch_condition = equal;
+
   } else {
     __ jmp(false_label, false_distance);
   }
index c7220afe1a4611e0a73b0d6b1cd97722f85b1f88..c37df961d6446a508ee15416666beb3dddbce97b 100644 (file)
@@ -109,6 +109,18 @@ Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg,
     function_index = Context::NUMBER_FUNCTION_INDEX;
   } else if (map()->instance_type() == FLOAT32X4_TYPE) {
     function_index = Context::FLOAT32X4_FUNCTION_INDEX;
+  } else if (map()->instance_type() == INT32X4_TYPE) {
+    function_index = Context::INT32X4_FUNCTION_INDEX;
+  } else if (map()->instance_type() == BOOL32X4_TYPE) {
+    function_index = Context::BOOL32X4_FUNCTION_INDEX;
+  } else if (map()->instance_type() == INT16X8_TYPE) {
+    function_index = Context::INT16X8_FUNCTION_INDEX;
+  } else if (map()->instance_type() == BOOL16X8_TYPE) {
+    function_index = Context::BOOL16X8_FUNCTION_INDEX;
+  } else if (map()->instance_type() == INT8X16_TYPE) {
+    function_index = Context::INT8X16_FUNCTION_INDEX;
+  } else if (map()->instance_type() == BOOL8X16_TYPE) {
+    function_index = Context::BOOL8X16_FUNCTION_INDEX;
   } else if (*map() == isolate()->heap()->boolean_map()) {
     function_index = Context::BOOLEAN_FUNCTION_INDEX;
   } else {
index f123595dd14e7417af7a916951760987ee0094b8..626748a804f2007242cf44ad94c85b39df200228 100644 (file)
@@ -138,6 +138,18 @@ JSFunction* IC::GetRootConstructor(Map* receiver_map, Context* native_context) {
     return native_context->symbol_function();
   } else if (receiver_map->instance_type() == FLOAT32X4_TYPE) {
     return native_context->float32x4_function();
+  } else if (receiver_map->instance_type() == INT32X4_TYPE) {
+    return native_context->int32x4_function();
+  } else if (receiver_map->instance_type() == BOOL32X4_TYPE) {
+    return native_context->bool32x4_function();
+  } else if (receiver_map->instance_type() == INT16X8_TYPE) {
+    return native_context->int16x8_function();
+  } else if (receiver_map->instance_type() == BOOL16X8_TYPE) {
+    return native_context->bool16x8_function();
+  } else if (receiver_map->instance_type() == INT8X16_TYPE) {
+    return native_context->int8x16_function();
+  } else if (receiver_map->instance_type() == BOOL8X16_TYPE) {
+    return native_context->bool8x16_function();
   } else {
     return NULL;
   }
index de5fe8bfa6084aff0700a00515269f7b3ad8c581..757d59fc48b1a0ec77290c470743433e52c9089f 100644 (file)
@@ -90,7 +90,6 @@ macro IS_NULL(arg)              = (arg === null);
 macro IS_NULL_OR_UNDEFINED(arg) = (arg == null);
 macro IS_UNDEFINED(arg)         = (arg === (void 0));
 macro IS_NUMBER(arg)            = (typeof(arg) === 'number');
-macro IS_FLOAT32X4(arg)         = (typeof(arg) === 'float32x4');
 macro IS_STRING(arg)            = (typeof(arg) === 'string');
 macro IS_BOOLEAN(arg)           = (typeof(arg) === 'boolean');
 macro IS_SYMBOL(arg)            = (typeof(arg) === 'symbol');
@@ -99,12 +98,12 @@ macro IS_ARRAY(arg)             = (%_IsArray(arg));
 macro IS_DATE(arg)              = (%_IsDate(arg));
 macro IS_FUNCTION(arg)          = (%_IsFunction(arg));
 macro IS_REGEXP(arg)            = (%_IsRegExp(arg));
+macro IS_SIMD_OBJECT(arg)       = (%_IsSimdObject(arg));
 macro IS_SET(arg)               = (%_ClassOf(arg) === 'Set');
 macro IS_MAP(arg)               = (%_ClassOf(arg) === 'Map');
 macro IS_WEAKMAP(arg)           = (%_ClassOf(arg) === 'WeakMap');
 macro IS_WEAKSET(arg)           = (%_ClassOf(arg) === 'WeakSet');
 macro IS_NUMBER_WRAPPER(arg)    = (%_ClassOf(arg) === 'Number');
-macro IS_FLOAT32X4_WRAPPER(arg) = (%_ClassOf(arg) === 'Float32x4');
 macro IS_STRING_WRAPPER(arg)    = (%_ClassOf(arg) === 'String');
 macro IS_SYMBOL_WRAPPER(arg)    = (%_ClassOf(arg) === 'Symbol');
 macro IS_BOOLEAN_WRAPPER(arg)   = (%_ClassOf(arg) === 'Boolean');
index 3829eda26ceff462e5ceecc307c6c2cbf9edd281..2101f79b990dbad7e1c6e47472e8571537b77a85 100644 (file)
@@ -86,7 +86,17 @@ function NoSideEffectToString(obj) {
     return str;
   }
   if (IS_SYMBOL(obj)) return %_CallFunction(obj, $symbolToString);
-  if (IS_FLOAT32X4(obj)) return %_CallFunction(obj, $float32x4ToString);
+  if (IS_SIMD_OBJECT(obj)) {
+    switch (typeof(obj)) {
+      case 'float32x4': return %_CallFunction(obj, $float32x4ToString);
+      case 'int32x4':   return %_CallFunction(obj, $int32x4ToString);
+      case 'bool32x4':  return %_CallFunction(obj, $bool32x4ToString);
+      case 'int16x8':   return %_CallFunction(obj, $int16x8ToString);
+      case 'bool16x8':  return %_CallFunction(obj, $bool16x8ToString);
+      case 'int16x8':   return %_CallFunction(obj, $int16x8ToString);
+      case 'bool16x8':  return %_CallFunction(obj, $bool16x8ToString);
+    }
+  }
   if (IS_OBJECT(obj)
       && %GetDataProperty(obj, "toString") === ObjectToString) {
     var constructor = %GetDataProperty(obj, "constructor");
index daff32fe945822265cadd7ad8404754f26d4a257..70df019caeaace2090aaeb898f1c75861ccf94eb 100644 (file)
@@ -291,12 +291,15 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow,
   // Smis. If it's not a heap number, then return equal.
   __ GetObjectType(a0, t4, t4);
   if (cc == less || cc == greater) {
+    Label not_simd;
     // Call runtime on identical JSObjects.
     __ Branch(slow, greater, t4, Operand(FIRST_SPEC_OBJECT_TYPE));
     // Call runtime on identical symbols since we need to throw a TypeError.
     __ Branch(slow, eq, t4, Operand(SYMBOL_TYPE));
     // Call runtime on identical SIMD values since we must throw a TypeError.
-    __ Branch(slow, eq, t4, Operand(FLOAT32X4_TYPE));
+    __ Branch(&not_simd, lt, t4, Operand(FIRST_SIMD_VALUE_TYPE));
+    __ Branch(slow, le, t4, Operand(LAST_SIMD_VALUE_TYPE));
+    __ bind(&not_simd);
     if (is_strong(strength)) {
       // Call the runtime on anything that is converted in the semantics, since
       // we need to throw a TypeError. Smis have already been ruled out.
@@ -305,6 +308,7 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow,
       __ Branch(slow, ne, t4, Operand(zero_reg));
     }
   } else {
+    Label not_simd;
     __ Branch(&heap_number, eq, t4, Operand(HEAP_NUMBER_TYPE));
     // Comparing JS objects with <=, >= is complicated.
     if (cc != eq) {
@@ -312,7 +316,9 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow,
     // Call runtime on identical symbols since we need to throw a TypeError.
     __ Branch(slow, eq, t4, Operand(SYMBOL_TYPE));
     // Call runtime on identical SIMD values since we must throw a TypeError.
-    __ Branch(slow, eq, t4, Operand(FLOAT32X4_TYPE));
+    __ Branch(&not_simd, lt, t4, Operand(FIRST_SIMD_VALUE_TYPE));
+    __ Branch(slow, le, t4, Operand(LAST_SIMD_VALUE_TYPE));
+    __ bind(&not_simd);
     if (is_strong(strength)) {
       // Call the runtime on anything that is converted in the semantics,
       // since we need to throw a TypeError. Smis and heap numbers have
index d6af3267c4452683b5e9fcfec05779239abc6d22..88adcd421769ccd5f448e5ba7ee66abd8f928e90 100644 (file)
@@ -2183,10 +2183,13 @@ void LCodeGen::DoBranch(LBranch* instr) {
 
       if (expected.Contains(ToBooleanStub::SIMD_VALUE)) {
         // SIMD value -> true.
+        Label not_simd;
         const Register scratch = scratch1();
         __ lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
-        __ Branch(instr->TrueLabel(chunk_), eq, scratch,
-                  Operand(FLOAT32X4_TYPE));
+        __ Branch(&not_simd, lt, at, Operand(FIRST_SIMD_VALUE_TYPE));
+        __ Branch(instr->TrueLabel(chunk_), le, scratch,
+                  Operand(LAST_SIMD_VALUE_TYPE));
+        __ bind(&not_simd);
       }
 
       if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
@@ -5748,6 +5751,48 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
     *cmp2 = Operand(FLOAT32X4_TYPE);
     final_branch_condition = eq;
 
+  } else if (String::Equals(type_name, factory->int32x4_string())) {
+    __ JumpIfSmi(input, false_label);
+    __ GetObjectType(input, input, scratch);
+    *cmp1 = scratch;
+    *cmp2 = Operand(INT32X4_TYPE);
+    final_branch_condition = eq;
+
+  } else if (String::Equals(type_name, factory->bool32x4_string())) {
+    __ JumpIfSmi(input, false_label);
+    __ GetObjectType(input, input, scratch);
+    *cmp1 = scratch;
+    *cmp2 = Operand(BOOL32X4_TYPE);
+    final_branch_condition = eq;
+
+  } else if (String::Equals(type_name, factory->int16x8_string())) {
+    __ JumpIfSmi(input, false_label);
+    __ GetObjectType(input, input, scratch);
+    *cmp1 = scratch;
+    *cmp2 = Operand(INT16X8_TYPE);
+    final_branch_condition = eq;
+
+  } else if (String::Equals(type_name, factory->bool16x8_string())) {
+    __ JumpIfSmi(input, false_label);
+    __ GetObjectType(input, input, scratch);
+    *cmp1 = scratch;
+    *cmp2 = Operand(BOOL16X8_TYPE);
+    final_branch_condition = eq;
+
+  } else if (String::Equals(type_name, factory->int8x16_string())) {
+    __ JumpIfSmi(input, false_label);
+    __ GetObjectType(input, input, scratch);
+    *cmp1 = scratch;
+    *cmp2 = Operand(INT8X16_TYPE);
+    final_branch_condition = eq;
+
+  } else if (String::Equals(type_name, factory->bool8x16_string())) {
+    __ JumpIfSmi(input, false_label);
+    __ GetObjectType(input, input, scratch);
+    *cmp1 = scratch;
+    *cmp2 = Operand(BOOL8X16_TYPE);
+    final_branch_condition = eq;
+
   } else {
     *cmp1 = at;
     *cmp2 = Operand(zero_reg);  // Set to valid regs, to avoid caller assertion.
index 8b46e4c72f1fc439ba6a937e226a1c270c7c5b28..59d36c5fb52c8fd4806fd64989ec644844cb207a 100644 (file)
@@ -287,12 +287,15 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow,
   // Smis. If it's not a heap number, then return equal.
   __ GetObjectType(a0, t0, t0);
   if (cc == less || cc == greater) {
+    Label not_simd;
     // Call runtime on identical JSObjects.
     __ Branch(slow, greater, t0, Operand(FIRST_SPEC_OBJECT_TYPE));
     // Call runtime on identical symbols since we need to throw a TypeError.
     __ Branch(slow, eq, t0, Operand(SYMBOL_TYPE));
     // Call runtime on identical SIMD values since we must throw a TypeError.
-    __ Branch(slow, eq, t0, Operand(FLOAT32X4_TYPE));
+    __ Branch(&not_simd, lt, t0, Operand(FIRST_SIMD_VALUE_TYPE));
+    __ Branch(slow, le, t0, Operand(LAST_SIMD_VALUE_TYPE));
+    __ bind(&not_simd);
     if (is_strong(strength)) {
       // Call the runtime on anything that is converted in the semantics, since
       // we need to throw a TypeError. Smis have already been ruled out.
@@ -304,18 +307,21 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow,
     __ Branch(&heap_number, eq, t0, Operand(HEAP_NUMBER_TYPE));
     // Comparing JS objects with <=, >= is complicated.
     if (cc != eq) {
-    __ Branch(slow, greater, t0, Operand(FIRST_SPEC_OBJECT_TYPE));
-    // Call runtime on identical symbols since we need to throw a TypeError.
-    __ Branch(slow, eq, t0, Operand(SYMBOL_TYPE));
-    // Call runtime on identical SIMD values since we must throw a TypeError.
-    __ Branch(slow, eq, t0, Operand(FLOAT32X4_TYPE));
-    if (is_strong(strength)) {
-      // Call the runtime on anything that is converted in the semantics,
-      // since we need to throw a TypeError. Smis and heap numbers have
-      // already been ruled out.
-      __ And(t0, t0, Operand(kIsNotStringMask));
-      __ Branch(slow, ne, t0, Operand(zero_reg));
-    }
+      Label not_simd;
+      __ Branch(slow, greater, t0, Operand(FIRST_SPEC_OBJECT_TYPE));
+      // Call runtime on identical symbols since we need to throw a TypeError.
+      __ Branch(slow, eq, t0, Operand(SYMBOL_TYPE));
+      // Call runtime on identical SIMD values since we must throw a TypeError.
+      __ Branch(&not_simd, lt, t0, Operand(FIRST_SIMD_VALUE_TYPE));
+      __ Branch(slow, le, t0, Operand(LAST_SIMD_VALUE_TYPE));
+      __ bind(&not_simd);
+      if (is_strong(strength)) {
+        // Call the runtime on anything that is converted in the semantics,
+        // since we need to throw a TypeError. Smis and heap numbers have
+        // already been ruled out.
+        __ And(t0, t0, Operand(kIsNotStringMask));
+        __ Branch(slow, ne, t0, Operand(zero_reg));
+      }
       // Normally here we fall through to return_equal, but undefined is
       // special: (undefined == undefined) == true, but
       // (undefined <= undefined) == false!  See ECMAScript 11.8.5.
index 15105aa738e8175286133360b943d7abe7614f06..fe8ee01eeef3962b4da293c22960615f8cf741ba 100644 (file)
@@ -2283,11 +2283,14 @@ void LCodeGen::DoBranch(LBranch* instr) {
       }
 
       if (expected.Contains(ToBooleanStub::SIMD_VALUE)) {
-        // Symbol value -> true.
+        // SIMD value -> true.
+        Label not_simd;
         const Register scratch = scratch1();
         __ lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
-        __ Branch(instr->TrueLabel(chunk_), eq, scratch,
-                  Operand(FLOAT32X4_TYPE));
+        __ Branch(&not_simd, lt, at, Operand(FIRST_SIMD_VALUE_TYPE));
+        __ Branch(instr->TrueLabel(chunk_), le, scratch,
+                  Operand(LAST_SIMD_VALUE_TYPE));
+        __ bind(&not_simd);
       }
 
       if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
@@ -5882,6 +5885,48 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
     *cmp2 = Operand(FLOAT32X4_TYPE);
     final_branch_condition = eq;
 
+  } else if (String::Equals(type_name, factory->int32x4_string())) {
+    __ JumpIfSmi(input, false_label);
+    __ GetObjectType(input, input, scratch);
+    *cmp1 = scratch;
+    *cmp2 = Operand(INT32X4_TYPE);
+    final_branch_condition = eq;
+
+  } else if (String::Equals(type_name, factory->bool32x4_string())) {
+    __ JumpIfSmi(input, false_label);
+    __ GetObjectType(input, input, scratch);
+    *cmp1 = scratch;
+    *cmp2 = Operand(BOOL32X4_TYPE);
+    final_branch_condition = eq;
+
+  } else if (String::Equals(type_name, factory->int16x8_string())) {
+    __ JumpIfSmi(input, false_label);
+    __ GetObjectType(input, input, scratch);
+    *cmp1 = scratch;
+    *cmp2 = Operand(INT16X8_TYPE);
+    final_branch_condition = eq;
+
+  } else if (String::Equals(type_name, factory->bool16x8_string())) {
+    __ JumpIfSmi(input, false_label);
+    __ GetObjectType(input, input, scratch);
+    *cmp1 = scratch;
+    *cmp2 = Operand(BOOL16X8_TYPE);
+    final_branch_condition = eq;
+
+  } else if (String::Equals(type_name, factory->int8x16_string())) {
+    __ JumpIfSmi(input, false_label);
+    __ GetObjectType(input, input, scratch);
+    *cmp1 = scratch;
+    *cmp2 = Operand(INT8X16_TYPE);
+    final_branch_condition = eq;
+
+  } else if (String::Equals(type_name, factory->bool8x16_string())) {
+    __ JumpIfSmi(input, false_label);
+    __ GetObjectType(input, input, scratch);
+    *cmp1 = scratch;
+    *cmp2 = Operand(BOOL8X16_TYPE);
+    final_branch_condition = eq;
+
   } else if (String::Equals(type_name, factory->boolean_string())) {
     __ LoadRoot(at, Heap::kTrueValueRootIndex);
     __ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input));
index 3a2ec3e559a16863db44acfcbce63a72cc9762aa..d2e66189d15c5c1f6b4a17d5cdb05458ef610c89 100644 (file)
@@ -61,6 +61,24 @@ void HeapObject::HeapObjectVerify() {
     case FLOAT32X4_TYPE:
       Float32x4::cast(this)->Float32x4Verify();
       break;
+    case INT32X4_TYPE:
+      Int32x4::cast(this)->Int32x4Verify();
+      break;
+    case BOOL32X4_TYPE:
+      Bool32x4::cast(this)->Bool32x4Verify();
+      break;
+    case INT16X8_TYPE:
+      Int16x8::cast(this)->Int16x8Verify();
+      break;
+    case BOOL16X8_TYPE:
+      Bool16x8::cast(this)->Bool16x8Verify();
+      break;
+    case INT8X16_TYPE:
+      Int8x16::cast(this)->Int8x16Verify();
+      break;
+    case BOOL8X16_TYPE:
+      Bool8x16::cast(this)->Bool8x16Verify();
+      break;
     case FIXED_ARRAY_TYPE:
       FixedArray::cast(this)->FixedArrayVerify();
       break;
@@ -217,6 +235,24 @@ void HeapNumber::HeapNumberVerify() {
 void Float32x4::Float32x4Verify() { CHECK(IsFloat32x4()); }
 
 
+void Int32x4::Int32x4Verify() { CHECK(IsInt32x4()); }
+
+
+void Bool32x4::Bool32x4Verify() { CHECK(IsBool32x4()); }
+
+
+void Int16x8::Int16x8Verify() { CHECK(IsInt16x8()); }
+
+
+void Bool16x8::Bool16x8Verify() { CHECK(IsBool16x8()); }
+
+
+void Int8x16::Int8x16Verify() { CHECK(IsInt8x16()); }
+
+
+void Bool8x16::Bool8x16Verify() { CHECK(IsBool8x16()); }
+
+
 void ByteArray::ByteArrayVerify() {
   CHECK(IsByteArray());
 }
index 4929c0d2dfd56a70900d070e8d2b2e87f52120c2..544c66a4cc4e2d3a59acd6e471e0bbc52f088aa4 100644 (file)
@@ -168,10 +168,26 @@ bool Object::IsHeapObject() const {
 
 TYPE_CHECKER(HeapNumber, HEAP_NUMBER_TYPE)
 TYPE_CHECKER(MutableHeapNumber, MUTABLE_HEAP_NUMBER_TYPE)
-TYPE_CHECKER(Float32x4, FLOAT32X4_TYPE)
 TYPE_CHECKER(Symbol, SYMBOL_TYPE)
 
 
+bool Object::IsSimd128Value() const {
+  if (!Object::IsHeapObject()) return false;
+  InstanceType instance_type = HeapObject::cast(this)->map()->instance_type();
+  return (instance_type >= FIRST_SIMD_VALUE_TYPE &&
+          instance_type <= LAST_SIMD_VALUE_TYPE);
+}
+
+
+TYPE_CHECKER(Float32x4, FLOAT32X4_TYPE)
+TYPE_CHECKER(Int32x4, INT32X4_TYPE)
+TYPE_CHECKER(Bool32x4, BOOL32X4_TYPE)
+TYPE_CHECKER(Int16x8, INT16X8_TYPE)
+TYPE_CHECKER(Bool16x8, BOOL16X8_TYPE)
+TYPE_CHECKER(Int8x16, INT8X16_TYPE)
+TYPE_CHECKER(Bool8x16, BOOL8X16_TYPE)
+
+
 bool Object::IsString() const {
   return Object::IsHeapObject()
     && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
@@ -1243,6 +1259,18 @@ MaybeHandle<Object> Object::GetProperty(Isolate* isolate, Handle<Object> object,
 #define WRITE_INTPTR_FIELD(p, offset, value) \
   (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
 
+#define READ_UINT16_FIELD(p, offset) \
+  (*reinterpret_cast<const uint16_t*>(FIELD_ADDR_CONST(p, offset)))
+
+#define WRITE_UINT16_FIELD(p, offset, value) \
+  (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
+
+#define READ_INT16_FIELD(p, offset) \
+  (*reinterpret_cast<const int16_t*>(FIELD_ADDR_CONST(p, offset)))
+
+#define WRITE_INT16_FIELD(p, offset, value) \
+  (*reinterpret_cast<int16_t*>(FIELD_ADDR(p, offset)) = value)
+
 #define READ_UINT32_FIELD(p, offset) \
   (*reinterpret_cast<const uint32_t*>(FIELD_ADDR_CONST(p, offset)))
 
@@ -1273,12 +1301,6 @@ MaybeHandle<Object> Object::GetProperty(Isolate* isolate, Handle<Object> object,
 #define WRITE_INT64_FIELD(p, offset, value) \
   (*reinterpret_cast<int64_t*>(FIELD_ADDR(p, offset)) = value)
 
-#define READ_SHORT_FIELD(p, offset) \
-  (*reinterpret_cast<const uint16_t*>(FIELD_ADDR_CONST(p, offset)))
-
-#define WRITE_SHORT_FIELD(p, offset, value) \
-  (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
-
 #define READ_BYTE_FIELD(p, offset) \
   (*reinterpret_cast<const byte*>(FIELD_ADDR_CONST(p, offset)))
 
@@ -1560,6 +1582,162 @@ void Float32x4::set_lane(int lane, float value) {
 }
 
 
+int32_t Int32x4::get_lane(int lane) const {
+  DCHECK(lane < 4 && lane >= 0);
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+  return READ_INT32_FIELD(this, kValueOffset + lane * kInt32Size);
+#elif defined(V8_TARGET_BIG_ENDIAN)
+  return READ_INT32_FIELD(this, kValueOffset + (3 - lane) * kInt32Size);
+#else
+#error Unknown byte ordering
+#endif
+}
+
+
+void Int32x4::set_lane(int lane, int32_t value) {
+  DCHECK(lane < 4 && lane >= 0);
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+  WRITE_INT32_FIELD(this, kValueOffset + lane * kInt32Size, value);
+#elif defined(V8_TARGET_BIG_ENDIAN)
+  WRITE_INT32_FIELD(this, kValueOffset + (3 - lane) * kInt32Size, value);
+#else
+#error Unknown byte ordering
+#endif
+}
+
+
+bool Bool32x4::get_lane(int lane) const {
+  DCHECK(lane < 4 && lane >= 0);
+  int32_t value;
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+  value = READ_INT32_FIELD(this, kValueOffset + lane * kInt32Size);
+#elif defined(V8_TARGET_BIG_ENDIAN)
+  value = READ_INT32_FIELD(this, kValueOffset + (3 - lane) * kInt32Size);
+#else
+#error Unknown byte ordering
+#endif
+  DCHECK(value == 0 || value == -1);
+  return value != 0;
+}
+
+
+void Bool32x4::set_lane(int lane, bool value) {
+  DCHECK(lane < 4 && lane >= 0);
+  int32_t int_val = value ? -1 : 0;
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+  WRITE_INT32_FIELD(this, kValueOffset + lane * kInt32Size, int_val);
+#elif defined(V8_TARGET_BIG_ENDIAN)
+  WRITE_INT32_FIELD(this, kValueOffset + (3 - lane) * kInt32Size, int_val);
+#else
+#error Unknown byte ordering
+#endif
+}
+
+
+int16_t Int16x8::get_lane(int lane) const {
+  DCHECK(lane < 8 && lane >= 0);
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+  return READ_INT16_FIELD(this, kValueOffset + lane * kShortSize);
+#elif defined(V8_TARGET_BIG_ENDIAN)
+  return READ_INT16_FIELD(this, kValueOffset + (7 - lane) * kShortSize);
+#else
+#error Unknown byte ordering
+#endif
+}
+
+
+void Int16x8::set_lane(int lane, int16_t value) {
+  DCHECK(lane < 8 && lane >= 0);
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+  WRITE_INT16_FIELD(this, kValueOffset + lane * kShortSize, value);
+#elif defined(V8_TARGET_BIG_ENDIAN)
+  WRITE_INT16_FIELD(this, kValueOffset + (7 - lane) * kShortSize, value);
+#else
+#error Unknown byte ordering
+#endif
+}
+
+
+bool Bool16x8::get_lane(int lane) const {
+  DCHECK(lane < 8 && lane >= 0);
+  int16_t value;
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+  return READ_INT16_FIELD(this, kValueOffset + lane * kShortSize);
+#elif defined(V8_TARGET_BIG_ENDIAN)
+  return READ_INT16_FIELD(this, kValueOffset + (7 - lane) * kShortSize);
+#else
+#error Unknown byte ordering
+#endif
+  DCHECK(value == 0 || value == -1);
+  return value != 0;
+}
+
+
+void Bool16x8::set_lane(int lane, bool value) {
+  DCHECK(lane < 8 && lane >= 0);
+  int16_t int_val = value ? -1 : 0;
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+  WRITE_INT16_FIELD(this, kValueOffset + lane * kShortSize, int_val);
+#elif defined(V8_TARGET_BIG_ENDIAN)
+  WRITE_INT16_FIELD(this, kValueOffset + (7 - lane) * kShortSize, int_val);
+#else
+#error Unknown byte ordering
+#endif
+}
+
+
+int8_t Int8x16::get_lane(int lane) const {
+  DCHECK(lane < 16 && lane >= 0);
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+  return READ_BYTE_FIELD(this, kValueOffset + lane * kCharSize);
+#elif defined(V8_TARGET_BIG_ENDIAN)
+  return READ_BYTE_FIELD(this, kValueOffset + (15 - lane) * kCharSize);
+#else
+#error Unknown byte ordering
+#endif
+}
+
+
+void Int8x16::set_lane(int lane, int8_t value) {
+  DCHECK(lane < 16 && lane >= 0);
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+  WRITE_BYTE_FIELD(this, kValueOffset + lane * kCharSize, value);
+#elif defined(V8_TARGET_BIG_ENDIAN)
+  WRITE_BYTE_FIELD(this, kValueOffset + (15 - lane) * kCharSize, value);
+#else
+#error Unknown byte ordering
+#endif
+}
+
+
+bool Bool8x16::get_lane(int lane) const {
+  DCHECK(lane < 16 && lane >= 0);
+  int8_t value;
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+  value = READ_BYTE_FIELD(this, kValueOffset + lane * kCharSize);
+#elif defined(V8_TARGET_BIG_ENDIAN)
+  value = READ_BYTE_FIELD(this, kValueOffset + (15 - lane) * kCharSize);
+#else
+#error Unknown byte ordering
+#endif
+  DCHECK(value == 0 || value == -1);
+  return value != 0;
+}
+
+
+void Bool8x16::set_lane(int lane, bool value) {
+  DCHECK(lane < 16 && lane >= 0);
+  int8_t int_val = value ? -1 : 0;
+#if defined(V8_TARGET_LITTLE_ENDIAN)
+  WRITE_BYTE_FIELD(this, kValueOffset + lane * kCharSize, int_val);
+#elif defined(V8_TARGET_BIG_ENDIAN)
+  WRITE_BYTE_FIELD(this, kValueOffset + (15 - lane) * kCharSize, int_val);
+#else
+#error Unknown byte ordering
+#endif
+}
+
+
 ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
 
 
@@ -2204,7 +2382,7 @@ bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
 void Object::VerifyApiCallResultType() {
 #if DEBUG
   if (!(IsSmi() || IsString() || IsSymbol() || IsSpecObject() ||
-        IsHeapNumber() || IsFloat32x4() || IsUndefined() || IsTrue() ||
+        IsHeapNumber() || IsSimd128Value() || IsUndefined() || IsTrue() ||
         IsFalse() || IsNull())) {
     FATAL("API call returned invalid object");
   }
@@ -2396,7 +2574,7 @@ AllocationAlignment HeapObject::RequiredAlignment() {
     return kDoubleAligned;
   }
   if (IsHeapNumber()) return kDoubleUnaligned;
-  if (IsFloat32x4()) return kSimd128Unaligned;
+  if (IsSimd128Value()) return kSimd128Unaligned;
 #endif  // V8_HOST_ARCH_32_BIT
   return kWordAligned;
 }
@@ -2908,6 +3086,9 @@ void SeededNumberDictionary::set_requires_slow_elements() {
 
 CAST_ACCESSOR(AccessorInfo)
 CAST_ACCESSOR(ArrayList)
+CAST_ACCESSOR(Bool16x8)
+CAST_ACCESSOR(Bool32x4)
+CAST_ACCESSOR(Bool8x16)
 CAST_ACCESSOR(ByteArray)
 CAST_ACCESSOR(BytecodeArray)
 CAST_ACCESSOR(Cell)
@@ -2932,6 +3113,9 @@ CAST_ACCESSOR(GlobalDictionary)
 CAST_ACCESSOR(GlobalObject)
 CAST_ACCESSOR(HandlerTable)
 CAST_ACCESSOR(HeapObject)
+CAST_ACCESSOR(Int16x8)
+CAST_ACCESSOR(Int32x4)
+CAST_ACCESSOR(Int8x16)
 CAST_ACCESSOR(JSArray)
 CAST_ACCESSOR(JSArrayBuffer)
 CAST_ACCESSOR(JSArrayBufferView)
@@ -2976,6 +3160,7 @@ CAST_ACCESSOR(SeqOneByteString)
 CAST_ACCESSOR(SeqString)
 CAST_ACCESSOR(SeqTwoByteString)
 CAST_ACCESSOR(SharedFunctionInfo)
+CAST_ACCESSOR(Simd128Value)
 CAST_ACCESSOR(SlicedString)
 CAST_ACCESSOR(Smi)
 CAST_ACCESSOR(String)
@@ -3311,13 +3496,13 @@ uc16* SeqTwoByteString::GetChars() {
 
 uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
   DCHECK(index >= 0 && index < length());
-  return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
+  return READ_UINT16_FIELD(this, kHeaderSize + index * kShortSize);
 }
 
 
 void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
   DCHECK(index >= 0 && index < length());
-  WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
+  WRITE_UINT16_FIELD(this, kHeaderSize + index * kShortSize, value);
 }
 
 
@@ -7088,10 +7273,20 @@ String::SubStringRange::iterator String::SubStringRange::end() {
 #undef WRITE_INT_FIELD
 #undef READ_INTPTR_FIELD
 #undef WRITE_INTPTR_FIELD
+#undef READ_UINT16_FIELD
+#undef WRITE_UINT16_FIELD
+#undef READ_INT16_FIELD
+#undef WRITE_INT16_FIELD
 #undef READ_UINT32_FIELD
 #undef WRITE_UINT32_FIELD
-#undef READ_SHORT_FIELD
-#undef WRITE_SHORT_FIELD
+#undef READ_INT32_FIELD
+#undef WRITE_INT32_FIELD
+#undef READ_FLOAT_FIELD
+#undef WRITE_FLOAT_FIELD
+#undef READ_UINT64_FIELD
+#undef WRITE_UINT64_FIELD
+#undef READ_INT64_FIELD
+#undef WRITE_INT64_FIELD
 #undef READ_BYTE_FIELD
 #undef WRITE_BYTE_FIELD
 #undef NOBARRIER_READ_BYTE_FIELD
index cb67d6a6e86a60d058af4cd21fae5ec163607086..560419b0db3a4984afa8ee202088e5442098ae07 100644 (file)
@@ -64,6 +64,24 @@ void HeapObject::HeapObjectPrint(std::ostream& os) {  // NOLINT
     case FLOAT32X4_TYPE:
       Float32x4::cast(this)->Float32x4Print(os);
       break;
+    case INT32X4_TYPE:
+      Int32x4::cast(this)->Int32x4Print(os);
+      break;
+    case BOOL32X4_TYPE:
+      Bool32x4::cast(this)->Bool32x4Print(os);
+      break;
+    case INT16X8_TYPE:
+      Int16x8::cast(this)->Int16x8Print(os);
+      break;
+    case BOOL16X8_TYPE:
+      Bool16x8::cast(this)->Bool16x8Print(os);
+      break;
+    case INT8X16_TYPE:
+      Int16x8::cast(this)->Int16x8Print(os);
+      break;
+    case BOOL8X16_TYPE:
+      Bool16x8::cast(this)->Bool16x8Print(os);
+      break;
     case FIXED_DOUBLE_ARRAY_TYPE:
       FixedDoubleArray::cast(this)->FixedDoubleArrayPrint(os);
       break;
@@ -192,6 +210,74 @@ void HeapObject::HeapObjectPrint(std::ostream& os) {  // NOLINT
 }
 
 
+void Float32x4::Float32x4Print(std::ostream& os) {  // NOLINT
+  char arr[100];
+  Vector<char> buffer(arr, arraysize(arr));
+  os << std::string(DoubleToCString(get_lane(0), buffer)) << ", "
+     << std::string(DoubleToCString(get_lane(1), buffer)) << ", "
+     << std::string(DoubleToCString(get_lane(2), buffer)) << ", "
+     << std::string(DoubleToCString(get_lane(3), buffer));
+}
+
+
+void Int32x4::Int32x4Print(std::ostream& os) {  // NOLINT
+  char arr[100];
+  Vector<char> buffer(arr, arraysize(arr));
+  os << std::string(IntToCString(get_lane(0), buffer)) << ", "
+     << std::string(IntToCString(get_lane(1), buffer)) << ", "
+     << std::string(IntToCString(get_lane(2), buffer)) << ", "
+     << std::string(IntToCString(get_lane(3), buffer));
+}
+
+
+void Bool32x4::Bool32x4Print(std::ostream& os) {  // NOLINT
+  os << std::string(get_lane(0) ? "true" : "false") << ", "
+     << std::string(get_lane(1) ? "true" : "false") << ", "
+     << std::string(get_lane(2) ? "true" : "false") << ", "
+     << std::string(get_lane(3) ? "true" : "false");
+}
+
+
+void Int16x8::Int16x8Print(std::ostream& os) {  // NOLINT
+  char arr[100];
+  Vector<char> buffer(arr, arraysize(arr));
+  os << std::string(IntToCString(get_lane(0), buffer));
+  for (int i = 1; i < 8; i++) {
+    os << ", " << std::string(IntToCString(get_lane(i), buffer));
+  }
+}
+
+
+void Bool16x8::Bool16x8Print(std::ostream& os) {  // NOLINT
+  char arr[100];
+  Vector<char> buffer(arr, arraysize(arr));
+  os << std::string(get_lane(0) ? "true" : "false");
+  for (int i = 1; i < 8; i++) {
+    os << ", " << std::string(get_lane(i) ? "true" : "false");
+  }
+}
+
+
+void Int8x16::Int8x16Print(std::ostream& os) {  // NOLINT
+  char arr[100];
+  Vector<char> buffer(arr, arraysize(arr));
+  os << std::string(IntToCString(get_lane(0), buffer));
+  for (int i = 1; i < 16; i++) {
+    os << ", " << std::string(IntToCString(get_lane(i), buffer));
+  }
+}
+
+
+void Bool8x16::Bool8x16Print(std::ostream& os) {  // NOLINT
+  char arr[100];
+  Vector<char> buffer(arr, arraysize(arr));
+  os << std::string(get_lane(0) ? "true" : "false");
+  for (int i = 1; i < 16; i++) {
+    os << ", " << std::string(get_lane(i) ? "true" : "false");
+  }
+}
+
+
 void ByteArray::ByteArrayPrint(std::ostream& os) {  // NOLINT
   os << "byte array, data starts at " << GetDataStartAddress();
 }
index 053f7107b8e6cb03aac35dac8507dd42d2b09563..1a0a3683b7b5568751aee4310d449549bdc4377c 100644 (file)
@@ -82,8 +82,24 @@ MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
     constructor = handle(native_context->string_function(), isolate);
   } else if (object->IsSymbol()) {
     constructor = handle(native_context->symbol_function(), isolate);
-  } else if (object->IsFloat32x4()) {
-    constructor = handle(native_context->float32x4_function(), isolate);
+  } else if (object->IsSimd128Value()) {
+    if (object->IsFloat32x4()) {
+      constructor = handle(native_context->float32x4_function(), isolate);
+    } else if (object->IsInt32x4()) {
+      constructor = handle(native_context->int32x4_function(), isolate);
+    } else if (object->IsBool32x4()) {
+      constructor = handle(native_context->bool32x4_function(), isolate);
+    } else if (object->IsInt16x8()) {
+      constructor = handle(native_context->int16x8_function(), isolate);
+    } else if (object->IsBool16x8()) {
+      constructor = handle(native_context->bool16x8_function(), isolate);
+    } else if (object->IsInt8x16()) {
+      constructor = handle(native_context->int8x16_function(), isolate);
+    } else if (object->IsBool8x16()) {
+      constructor = handle(native_context->bool8x16_function(), isolate);
+    } else {
+      UNREACHABLE();
+    }
   } else {
     return MaybeHandle<JSReceiver>();
   }
@@ -100,7 +116,7 @@ bool Object::BooleanValue() {
   if (IsUndetectableObject()) return false;   // Undetectable object is false.
   if (IsString()) return String::cast(this)->length() != 0;
   if (IsHeapNumber()) return HeapNumber::cast(this)->HeapNumberBooleanValue();
-  if (IsFloat32x4()) return true;  // Simd value types always evaluate to true.
+  if (IsSimd128Value()) return true;  // Simd value types evaluate to true.
   return true;
 }
 
@@ -629,8 +645,24 @@ Map* Object::GetRootMap(Isolate* isolate) {
   if (heap_object->IsBoolean()) {
     return context->boolean_function()->initial_map();
   }
-  if (heap_object->IsFloat32x4()) {
-    return context->float32x4_function()->initial_map();
+  if (heap_object->IsSimd128Value()) {
+    if (heap_object->IsFloat32x4()) {
+      return context->float32x4_function()->initial_map();
+    } else if (heap_object->IsInt32x4()) {
+      return context->int32x4_function()->initial_map();
+    } else if (heap_object->IsBool32x4()) {
+      return context->bool32x4_function()->initial_map();
+    } else if (heap_object->IsInt16x8()) {
+      return context->int16x8_function()->initial_map();
+    } else if (heap_object->IsBool16x8()) {
+      return context->bool16x8_function()->initial_map();
+    } else if (heap_object->IsInt8x16()) {
+      return context->int8x16_function()->initial_map();
+    } else if (heap_object->IsBool8x16()) {
+      return context->bool8x16_function()->initial_map();
+    } else {
+      UNREACHABLE();
+    }
   }
   return isolate->heap()->null_value()->map();
 }
@@ -670,14 +702,8 @@ Object* Object::GetSimpleHash() {
     uint32_t hash = Oddball::cast(this)->to_string()->Hash();
     return Smi::FromInt(hash);
   }
-  if (IsFloat32x4()) {
-    Float32x4* simd = Float32x4::cast(this);
-    uint32_t seed = v8::internal::kZeroHashSeed;
-    uint32_t hash;
-    hash = ComputeIntegerHash(bit_cast<uint32_t>(simd->get_lane(0)), seed);
-    hash = ComputeIntegerHash(bit_cast<uint32_t>(simd->get_lane(1)), hash * 31);
-    hash = ComputeIntegerHash(bit_cast<uint32_t>(simd->get_lane(2)), hash * 31);
-    hash = ComputeIntegerHash(bit_cast<uint32_t>(simd->get_lane(3)), hash * 31);
+  if (IsSimd128Value()) {
+    uint32_t hash = Simd128Value::cast(this)->Hash();
     return Smi::FromInt(hash & Smi::kMaxValue);
   }
   DCHECK(IsJSReceiver());
@@ -701,18 +727,37 @@ bool Object::SameValue(Object* other) {
   // The object is either a number, a name, an odd-ball,
   // a real JS object, or a Harmony proxy.
   if (IsNumber() && other->IsNumber()) {
-    return v8::internal::SameValue(Number(), other->Number());
+    double this_value = Number();
+    double other_value = other->Number();
+    // SameValue(NaN, NaN) is true.
+    if (this_value != other_value) {
+      return std::isnan(this_value) && std::isnan(other_value);
+    }
+    // SameValue(0.0, -0.0) is false.
+    return (std::signbit(this_value) == std::signbit(other_value));
   }
   if (IsString() && other->IsString()) {
     return String::cast(this)->Equals(String::cast(other));
   }
-  if (IsFloat32x4() && other->IsFloat32x4()) {
-    Float32x4* x = Float32x4::cast(this);
-    Float32x4* y = Float32x4::cast(other);
-    return v8::internal::SameValue(x->get_lane(0), y->get_lane(0)) &&
-           v8::internal::SameValue(x->get_lane(1), y->get_lane(1)) &&
-           v8::internal::SameValue(x->get_lane(2), y->get_lane(2)) &&
-           v8::internal::SameValue(x->get_lane(3), y->get_lane(3));
+  if (IsSimd128Value() && other->IsSimd128Value()) {
+    if (IsFloat32x4() && other->IsFloat32x4()) {
+      Float32x4* a = Float32x4::cast(this);
+      Float32x4* b = Float32x4::cast(other);
+      for (int i = 0; i < 4; i++) {
+        float x = a->get_lane(i);
+        float y = b->get_lane(i);
+        // Implements the ES5 SameValue operation for floating point types.
+        // http://www.ecma-international.org/ecma-262/6.0/#sec-samevalue
+        if (x != y && !(std::isnan(x) && std::isnan(y))) return false;
+        if (std::signbit(x) != std::signbit(y)) return false;
+      }
+      return true;
+    } else {
+      Simd128Value* a = Simd128Value::cast(this);
+      Simd128Value* b = Simd128Value::cast(other);
+      return a->map()->instance_type() == b->map()->instance_type() &&
+             a->BitwiseEquals(b);
+    }
   }
   return false;
 }
@@ -724,18 +769,34 @@ bool Object::SameValueZero(Object* other) {
   // The object is either a number, a name, an odd-ball,
   // a real JS object, or a Harmony proxy.
   if (IsNumber() && other->IsNumber()) {
-    return v8::internal::SameValueZero(Number(), other->Number());
+    double this_value = Number();
+    double other_value = other->Number();
+    // +0 == -0 is true
+    return this_value == other_value ||
+           (std::isnan(this_value) && std::isnan(other_value));
   }
   if (IsString() && other->IsString()) {
     return String::cast(this)->Equals(String::cast(other));
   }
-  if (IsFloat32x4() && other->IsFloat32x4()) {
-    Float32x4* x = Float32x4::cast(this);
-    Float32x4* y = Float32x4::cast(other);
-    return v8::internal::SameValueZero(x->get_lane(0), y->get_lane(0)) &&
-           v8::internal::SameValueZero(x->get_lane(1), y->get_lane(1)) &&
-           v8::internal::SameValueZero(x->get_lane(2), y->get_lane(2)) &&
-           v8::internal::SameValueZero(x->get_lane(3), y->get_lane(3));
+  if (IsSimd128Value() && other->IsSimd128Value()) {
+    if (IsFloat32x4() && other->IsFloat32x4()) {
+      Float32x4* a = Float32x4::cast(this);
+      Float32x4* b = Float32x4::cast(other);
+      for (int i = 0; i < 4; i++) {
+        float x = a->get_lane(i);
+        float y = b->get_lane(i);
+        // Implements the ES6 SameValueZero operation for floating point types.
+        // http://www.ecma-international.org/ecma-262/6.0/#sec-samevaluezero
+        if (x != y && !(std::isnan(x) && std::isnan(y))) return false;
+        // SameValueZero doesn't distinguish between 0 and -0.
+      }
+      return true;
+    } else {
+      Simd128Value* a = Simd128Value::cast(this);
+      Simd128Value* b = Simd128Value::cast(other);
+      return a->map()->instance_type() == b->map()->instance_type() &&
+             a->BitwiseEquals(b);
+    }
   }
   return false;
 }
@@ -1347,12 +1408,27 @@ void HeapObject::HeapObjectShortPrint(std::ostream& os) {  // NOLINT
       os << '>';
       break;
     }
-    case FLOAT32X4_TYPE: {
-      os << "<Float32x4: ";
-      Float32x4::cast(this)->Float32x4Print(os);
-      os << ">";
+    case FLOAT32X4_TYPE:
+      os << "<Float32x4>";
+      break;
+    case INT32X4_TYPE:
+      os << "<Int32x4>";
+      break;
+    case BOOL32X4_TYPE:
+      os << "<Bool32x4>";
+      break;
+    case INT16X8_TYPE:
+      os << "<Int16x8>";
+      break;
+    case BOOL16X8_TYPE:
+      os << "<Bool16x8>";
+      break;
+    case INT8X16_TYPE:
+      os << "<Int8x16>";
+      break;
+    case BOOL8X16_TYPE:
+      os << "<Bool8x16>";
       break;
-    }
     case JS_PROXY_TYPE:
       os << "<JSProxy>";
       break;
@@ -1497,6 +1573,12 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
     case HEAP_NUMBER_TYPE:
     case MUTABLE_HEAP_NUMBER_TYPE:
     case FLOAT32X4_TYPE:
+    case INT32X4_TYPE:
+    case BOOL32X4_TYPE:
+    case INT16X8_TYPE:
+    case BOOL16X8_TYPE:
+    case INT8X16_TYPE:
+    case BOOL8X16_TYPE:
     case FILLER_TYPE:
     case BYTE_ARRAY_TYPE:
     case BYTECODE_ARRAY_TYPE:
@@ -1545,13 +1627,35 @@ void HeapNumber::HeapNumberPrint(std::ostream& os) {  // NOLINT
 }
 
 
-void Float32x4::Float32x4Print(std::ostream& os) {  // NOLINT
-  char arr[100];
-  Vector<char> buffer(arr, arraysize(arr));
-  os << std::string(DoubleToCString(get_lane(0), buffer)) << ", "
-     << std::string(DoubleToCString(get_lane(1), buffer)) << ", "
-     << std::string(DoubleToCString(get_lane(2), buffer)) << ", "
-     << std::string(DoubleToCString(get_lane(3), buffer));
+#define FIELD_ADDR_CONST(p, offset) \
+  (reinterpret_cast<const byte*>(p) + offset - kHeapObjectTag)
+
+#define READ_INT32_FIELD(p, offset) \
+  (*reinterpret_cast<const int32_t*>(FIELD_ADDR_CONST(p, offset)))
+
+#define READ_INT64_FIELD(p, offset) \
+  (*reinterpret_cast<const int64_t*>(FIELD_ADDR_CONST(p, offset)))
+
+
+bool Simd128Value::BitwiseEquals(const Simd128Value* other) const {
+  return READ_INT64_FIELD(this, kValueOffset) ==
+             READ_INT64_FIELD(other, kValueOffset) &&
+         READ_INT64_FIELD(this, kValueOffset + kInt64Size) ==
+             READ_INT64_FIELD(other, kValueOffset + kInt64Size);
+}
+
+
+uint32_t Simd128Value::Hash() const {
+  uint32_t seed = v8::internal::kZeroHashSeed;
+  uint32_t hash;
+  hash = ComputeIntegerHash(READ_INT32_FIELD(this, kValueOffset), seed);
+  hash = ComputeIntegerHash(
+      READ_INT32_FIELD(this, kValueOffset + 1 * kInt32Size), hash * 31);
+  hash = ComputeIntegerHash(
+      READ_INT32_FIELD(this, kValueOffset + 2 * kInt32Size), hash * 31);
+  hash = ComputeIntegerHash(
+      READ_INT32_FIELD(this, kValueOffset + 3 * kInt32Size), hash * 31);
+  return hash;
 }
 
 
index 9663398ad02bdff4574fc7d91c9c55ab18199187..ee83e3b7a261e6aedce7d333b16e8e7c9f89f0d4 100644 (file)
 //             - ExternalTwoByteInternalizedString
 //       - Symbol
 //     - HeapNumber
-//     - Float32x4
+//     - Simd128Value
+//       - Float32x4
+//       - Int32x4
+//       - Bool32x4
+//       - Int16x8
+//       - Bool16x8
+//       - Int8x16
+//       - Bool8x16
 //     - Cell
 //     - PropertyCell
 //     - Code
@@ -370,6 +377,12 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
                                                                 \
   V(SYMBOL_TYPE)                                                \
   V(FLOAT32X4_TYPE)                                             \
+  V(INT32X4_TYPE)                                               \
+  V(BOOL32X4_TYPE)                                              \
+  V(INT16X8_TYPE)                                               \
+  V(BOOL16X8_TYPE)                                              \
+  V(INT8X16_TYPE)                                               \
+  V(BOOL8X16_TYPE)                                              \
                                                                 \
   V(MAP_TYPE)                                                   \
   V(CODE_TYPE)                                                  \
@@ -663,12 +676,18 @@ enum InstanceType {
   // objects.
   HEAP_NUMBER_TYPE,
   MUTABLE_HEAP_NUMBER_TYPE,
-  FLOAT32X4_TYPE,  // FIRST_SIMD_TYPE, LAST_SIMD_TYPE
+  FLOAT32X4_TYPE,  // FIRST_SIMD_VALUE_TYPE
+  INT32X4_TYPE,
+  BOOL32X4_TYPE,
+  INT16X8_TYPE,
+  BOOL16X8_TYPE,
+  INT8X16_TYPE,
+  BOOL8X16_TYPE,  // LAST_SIMD_VALUE_TYPE
   FOREIGN_TYPE,
   BYTE_ARRAY_TYPE,
   BYTECODE_ARRAY_TYPE,
   FREE_SPACE_TYPE,
-  FIXED_INT8_ARRAY_TYPE,              // FIRST_FIXED_TYPED_ARRAY_TYPE
+  FIXED_INT8_ARRAY_TYPE,  // FIRST_FIXED_TYPED_ARRAY_TYPE
   FIXED_UINT8_ARRAY_TYPE,
   FIXED_INT16_ARRAY_TYPE,
   FIXED_UINT16_ARRAY_TYPE,
@@ -747,9 +766,9 @@ enum InstanceType {
   FIRST_UNIQUE_NAME_TYPE = INTERNALIZED_STRING_TYPE,
   LAST_UNIQUE_NAME_TYPE = SYMBOL_TYPE,
   FIRST_NONSTRING_TYPE = SYMBOL_TYPE,
-  // Boundaries for testing for a SIMD type.
-  FIRST_SIMD_TYPE = FLOAT32X4_TYPE,
-  LAST_SIMD_TYPE = FLOAT32X4_TYPE,
+  // Boundaries for testing for a SIMD types.
+  FIRST_SIMD_VALUE_TYPE = FLOAT32X4_TYPE,
+  LAST_SIMD_VALUE_TYPE = BOOL8X16_TYPE,
   // Boundaries for testing for a fixed typed array.
   FIRST_FIXED_TYPED_ARRAY_TYPE = FIXED_INT8_ARRAY_TYPE,
   LAST_FIXED_TYPED_ARRAY_TYPE = FIXED_UINT8_CLAMPED_ARRAY_TYPE,
@@ -882,7 +901,14 @@ template <class C> inline bool Is(Object* obj);
 #define HEAP_OBJECT_TYPE_LIST(V)   \
   V(HeapNumber)                    \
   V(MutableHeapNumber)             \
+  V(Simd128Value)                  \
   V(Float32x4)                     \
+  V(Int32x4)                       \
+  V(Bool32x4)                      \
+  V(Int16x8)                       \
+  V(Bool16x8)                      \
+  V(Int8x16)                       \
+  V(Bool8x16)                      \
   V(Name)                          \
   V(UniqueName)                    \
   V(String)                        \
@@ -1578,26 +1604,50 @@ class HeapNumber: public HeapObject {
 };
 
 
-// The Float32x4 class describes heap allocated SIMD values holding 4 32-bit
-// IEEE floats.
-class Float32x4 : public HeapObject {
+// The SimdValue128 class describes heap allocated 128 bit SIMD values.
+class Simd128Value : public HeapObject {
  public:
-  inline float get_lane(int lane) const;
-  inline void set_lane(int lane, float value);
+  DECLARE_CAST(Simd128Value)
 
-  DECLARE_CAST(Float32x4)
-
-  // Dispatched behavior.
-  void Float32x4Print(std::ostream& os);  // NOLINT
-  DECLARE_VERIFIER(Float32x4)
+  // Checks that another instance is bit-wise equal.
+  bool BitwiseEquals(const Simd128Value* other) const;
+  // Computes a hash from the 128 bit value, viewed as 4 32-bit integers.
+  uint32_t Hash() const;
 
   // Layout description.
   static const int kValueOffset = HeapObject::kHeaderSize;
   static const int kSize = kValueOffset + kSimd128Size;
 
  private:
-  DISALLOW_IMPLICIT_CONSTRUCTORS(Float32x4);
-};
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Simd128Value);
+};
+
+
+#define SIMD128_TYPES(V)            \
+  V(Float32x4, float32x4, 4, float) \
+  V(Int32x4, int32x4, 4, int32_t)   \
+  V(Bool32x4, bool32x4, 4, bool)    \
+  V(Int16x8, int16x8, 8, int16_t)   \
+  V(Bool16x8, bool16x8, 8, bool)    \
+  V(Int8x16, int8x16, 16, int8_t)   \
+  V(Bool8x16, bool8x16, 16, bool)
+
+#define SIMD128_VALUE_CLASS(name, type, lane_count, lane_type) \
+  class name : public Simd128Value {                           \
+   public:                                                     \
+    inline lane_type get_lane(int lane) const;                 \
+    inline void set_lane(int lane, lane_type value);           \
+                                                               \
+    DECLARE_CAST(name)                                         \
+                                                               \
+    DECLARE_PRINTER(name)                                      \
+    DECLARE_VERIFIER(name)                                     \
+                                                               \
+   private:                                                    \
+    DISALLOW_IMPLICIT_CONSTRUCTORS(name);                      \
+  };
+
+SIMD128_TYPES(SIMD128_VALUE_CLASS)
 
 
 enum EnsureElementsMode {
index 59aa8b182a8b6355188759f5f6c5eb649aa3b34e..35e9f29fd13ecaaa05b394d9eb5a5c6a65f91267 100644 (file)
@@ -260,6 +260,7 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow,
   // They are both equal and they are not both Smis so both of them are not
   // Smis.  If it's not a heap number, then return equal.
   if (cond == lt || cond == gt) {
+    Label not_simd;
     // Call runtime on identical JSObjects.
     __ CompareObjectType(r3, r7, r7, FIRST_SPEC_OBJECT_TYPE);
     __ bge(slow);
@@ -267,8 +268,11 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow,
     __ cmpi(r7, Operand(SYMBOL_TYPE));
     __ beq(slow);
     // Call runtime on identical SIMD values since we must throw a TypeError.
-    __ cmpi(r7, Operand(FLOAT32X4_TYPE));
-    __ beq(slow);
+    __ cmpi(r7, Operand(FIRST_SIMD_VALUE_TYPE));
+    __ blt(&not_simd);
+    __ cmpi(r7, Operand(LAST_SIMD_VALUE_TYPE));
+    __ ble(slow);
+    __ bind(&not_simd);
     if (is_strong(strength)) {
       // Call the runtime on anything that is converted in the semantics, since
       // we need to throw a TypeError. Smis have already been ruled out.
@@ -282,14 +286,18 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow,
     __ beq(&heap_number);
     // Comparing JS objects with <=, >= is complicated.
     if (cond != eq) {
+      Label not_simd;
       __ cmpi(r7, Operand(FIRST_SPEC_OBJECT_TYPE));
       __ bge(slow);
       // Call runtime on identical symbols since we need to throw a TypeError.
       __ cmpi(r7, Operand(SYMBOL_TYPE));
       __ beq(slow);
       // Call runtime on identical SIMD values since we must throw a TypeError.
-      __ cmpi(r7, Operand(FLOAT32X4_TYPE));
-      __ beq(slow);
+      __ cmpi(r7, Operand(FIRST_SIMD_VALUE_TYPE));
+      __ blt(&not_simd);
+      __ cmpi(r7, Operand(LAST_SIMD_VALUE_TYPE));
+      __ ble(slow);
+      __ bind(&not_simd);
       if (is_strong(strength)) {
         // Call the runtime on anything that is converted in the semantics,
         // since we need to throw a TypeError. Smis and heap numbers have
index e5dd69aa12dc43416413dcc4ef516e4bbb1a9046..caf811654c67aa449d185c0ddde4af2707649825 100644 (file)
@@ -2307,8 +2307,12 @@ void LCodeGen::DoBranch(LBranch* instr) {
 
       if (expected.Contains(ToBooleanStub::SIMD_VALUE)) {
         // SIMD value -> true.
-        __ CompareInstanceType(map, ip, FLOAT32X4_TYPE);
-        __ beq(instr->TrueLabel(chunk_));
+        Label not_simd;
+        __ CompareInstanceType(map, ip, FIRST_SIMD_VALUE_TYPE);
+        __ blt(&not_simd);
+        __ CompareInstanceType(map, ip, LAST_SIMD_VALUE_TYPE);
+        __ ble(instr->TrueLabel(chunk_));
+        __ bind(&not_simd);
       }
 
       if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
@@ -5992,6 +5996,36 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label, Label* false_label,
     __ CompareObjectType(input, scratch, no_reg, FLOAT32X4_TYPE);
     final_branch_condition = eq;
 
+  } else if (String::Equals(type_name, factory->int32x4_string())) {
+    __ JumpIfSmi(input, false_label);
+    __ CompareObjectType(input, scratch, no_reg, INT32X4_TYPE);
+    final_branch_condition = eq;
+
+  } else if (String::Equals(type_name, factory->bool32x4_string())) {
+    __ JumpIfSmi(input, false_label);
+    __ CompareObjectType(input, scratch, no_reg, BOOL32X4_TYPE);
+    final_branch_condition = eq;
+
+  } else if (String::Equals(type_name, factory->int16x8_string())) {
+    __ JumpIfSmi(input, false_label);
+    __ CompareObjectType(input, scratch, no_reg, INT16X8_TYPE);
+    final_branch_condition = eq;
+
+  } else if (String::Equals(type_name, factory->bool16x8_string())) {
+    __ JumpIfSmi(input, false_label);
+    __ CompareObjectType(input, scratch, no_reg, BOOL16X8_TYPE);
+    final_branch_condition = eq;
+
+  } else if (String::Equals(type_name, factory->int8x16_string())) {
+    __ JumpIfSmi(input, false_label);
+    __ CompareObjectType(input, scratch, no_reg, INT8X16_TYPE);
+    final_branch_condition = eq;
+
+  } else if (String::Equals(type_name, factory->bool8x16_string())) {
+    __ JumpIfSmi(input, false_label);
+    __ CompareObjectType(input, scratch, no_reg, BOOL8X16_TYPE);
+    final_branch_condition = eq;
+
   } else {
     __ b(false_label);
   }
index 000d49756563dc02e5f3ce310d5cca641d7d1c67..b4bec8ae89529c473db6ab0b89631d0302064c89 100644 (file)
@@ -101,8 +101,8 @@ EQUALS = function EQUALS(y) {
       while (true) {
         if (IS_NUMBER(y)) return %NumberEquals(x, y);
         if (IS_NULL_OR_UNDEFINED(y)) return 1;  // not equal
-        if (IS_SYMBOL(y) || IS_FLOAT32X4(y)) return 1;  // not equal
         if (!IS_SPEC_OBJECT(y)) {
+          if (IS_SYMBOL(y) || IS_SIMD_OBJECT(y)) return 1;  // not equal
           // String or boolean.
           return %NumberEquals(x, %$toNumber(y));
         }
@@ -111,10 +111,10 @@ EQUALS = function EQUALS(y) {
     } else if (IS_STRING(x)) {
       while (true) {
         if (IS_STRING(y)) return %StringEquals(x, y);
-        if (IS_SYMBOL(y) || IS_FLOAT32X4(y)) return 1;  // not equal
         if (IS_NUMBER(y)) return %NumberEquals(%$toNumber(x), y);
         if (IS_BOOLEAN(y)) return %NumberEquals(%$toNumber(x), %$toNumber(y));
         if (IS_NULL_OR_UNDEFINED(y)) return 1;  // not equal
+        if (IS_SYMBOL(y) || IS_SIMD_OBJECT(y)) return 1;  // not equal
         y = %$toPrimitive(y, NO_HINT);
       }
     } else if (IS_SYMBOL(x)) {
@@ -125,24 +125,23 @@ EQUALS = function EQUALS(y) {
       if (IS_NULL_OR_UNDEFINED(y)) return 1;
       if (IS_NUMBER(y)) return %NumberEquals(%$toNumber(x), y);
       if (IS_STRING(y)) return %NumberEquals(%$toNumber(x), %$toNumber(y));
-      if (IS_SYMBOL(y) || IS_FLOAT32X4(y)) return 1;  // not equal
+      if (IS_SYMBOL(y) || IS_SIMD_OBJECT(y)) return 1;  // not equal
       // y is object.
       x = %$toNumber(x);
       y = %$toPrimitive(y, NO_HINT);
     } else if (IS_NULL_OR_UNDEFINED(x)) {
       return IS_NULL_OR_UNDEFINED(y) ? 0 : 1;
-    } else if (IS_FLOAT32X4(x)) {
-      if (IS_FLOAT32X4(y))
-        return %Float32x4Equals(x, y);
-      return 1;  // not equal
+    } else if (IS_SIMD_OBJECT(x)) {
+       return %SimdEquals(x, y);
     } else {
       // x is an object.
-      if (IS_SPEC_OBJECT(y)) {
-        return %_ObjectEquals(x, y) ? 0 : 1;
-      }
+      if (IS_SPEC_OBJECT(y)) return %_ObjectEquals(x, y) ? 0 : 1;
       if (IS_NULL_OR_UNDEFINED(y)) return 1;  // not equal
-      if (IS_SYMBOL(y) || IS_FLOAT32X4(y)) return 1;  // not equal
-      if (IS_BOOLEAN(y)) y = %$toNumber(y);
+      if (IS_BOOLEAN(y)) {
+        y = %$toNumber(y);
+      } else if (IS_SYMBOL(y) || IS_SIMD_OBJECT(y)) {
+        return 1;  // not equal
+      }
       x = %$toPrimitive(x, NO_HINT);
     }
   }
@@ -160,8 +159,7 @@ STRICT_EQUALS = function STRICT_EQUALS(x) {
     return %NumberEquals(this, x);
   }
 
-  if (IS_FLOAT32X4(this) && IS_FLOAT32X4(x))
-    return %Float32x4Equals(this, x);
+  if (IS_SIMD_OBJECT(this)) return %SimdEquals(this, x);
 
   // If anything else gets here, we just do simple identity check.
   // Objects (including functions), null, undefined and booleans were
@@ -758,7 +756,7 @@ function ToPrimitive(x, hint) {
   if (IS_STRING(x)) return x;
   // Normal behavior.
   if (!IS_SPEC_OBJECT(x)) return x;
-  if (IS_FLOAT32X4(x)) return x;
+  if (IS_SIMD_OBJECT(x)) return x;
   if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT;
   return (hint == NUMBER_HINT) ? DefaultNumber(x) : DefaultString(x);
 }
@@ -864,9 +862,7 @@ function SameValue(x, y) {
       return false;
     }
   }
-  if (IS_FLOAT32X4(x)) {
-    return %Float32x4SameValue(x, y);
-  }
+  if (IS_SIMD_OBJECT(x)) return %SimdSameValue(x, y);
   return x === y;
 }
 
@@ -877,9 +873,7 @@ function SameValueZero(x, y) {
   if (IS_NUMBER(x)) {
     if (NUMBER_IS_NAN(x) && NUMBER_IS_NAN(y)) return true;
   }
-  if (IS_FLOAT32X4(x)) {
-    return %Float32x4SameValueZero(x, y);
-  }
+  if (IS_SIMD_OBJECT(x)) return %SimdSameValueZero(x, y);
   return x === y;
 }
 
@@ -923,7 +917,7 @@ function DefaultNumber(x) {
   if (IS_SPEC_FUNCTION(valueOf)) {
     var v = %_CallFunction(x, valueOf);
     if (IS_SYMBOL(v)) throw MakeTypeError(kSymbolToNumber);
-    if (IS_FLOAT32X4(v)) throw MakeTypeError(kSimdToNumber);
+    if (IS_SIMD_OBJECT(x)) throw MakeTypeError(kSimdToNumber);
     if (IsPrimitive(v)) return v;
   }
   var toString = x.toString;
index 12c317147326b6fe36994302b8fc7be75f2104c9..90f1904f77001c0a266376a5d70b40b1e38246b7 100644 (file)
 // the SIMD.js draft spec:
 // http://littledan.github.io/simd.html
 
-#define NumberToFloat32x4Component NumberToFloat
-
 #define CONVERT_SIMD_LANE_ARG_CHECKED(name, index, lanes) \
-  RUNTIME_ASSERT(args[index]->IsSmi());                   \
-  int name = args.smi_at(index);                          \
+  CONVERT_INT32_ARG_CHECKED(name, index);                 \
   RUNTIME_ASSERT(name >= 0 && name < lanes);
 
-#define SIMD4_CREATE_FUNCTION(type)                                    \
-  RUNTIME_FUNCTION(Runtime_Create##type) {                             \
-    HandleScope scope(isolate);                                        \
-    DCHECK(args.length() == 4);                                        \
-    CONVERT_NUMBER_ARG_HANDLE_CHECKED(w, 0);                           \
-    CONVERT_NUMBER_ARG_HANDLE_CHECKED(x, 1);                           \
-    CONVERT_NUMBER_ARG_HANDLE_CHECKED(y, 2);                           \
-    CONVERT_NUMBER_ARG_HANDLE_CHECKED(z, 3);                           \
-    return *isolate->factory()->NewFloat32x4(                          \
-        NumberTo##type##Component(*w), NumberTo##type##Component(*x),  \
-        NumberTo##type##Component(*y), NumberTo##type##Component(*z)); \
+#define SIMD_CREATE_NUMERIC_FUNCTION(type, lane_type, lane_count) \
+  RUNTIME_FUNCTION(Runtime_Create##type) {                        \
+    HandleScope scope(isolate);                                   \
+    DCHECK(args.length() == lane_count);                          \
+    lane_type lanes[lane_count];                                  \
+    for (int i = 0; i < lane_count; i++) {                        \
+      CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, i);               \
+      lanes[i] = ConvertNumber<lane_type>(number->Number());      \
+    }                                                             \
+    return *isolate->factory()->New##type(lanes);                 \
+  }
+
+#define SIMD_CREATE_BOOLEAN_FUNCTION(type, lane_count) \
+  RUNTIME_FUNCTION(Runtime_Create##type) {             \
+    HandleScope scope(isolate);                        \
+    DCHECK(args.length() == lane_count);               \
+    bool lanes[lane_count];                            \
+    for (int i = 0; i < lane_count; i++) {             \
+      lanes[i] = args[i]->BooleanValue();              \
+    }                                                  \
+    return *isolate->factory()->New##type(lanes);      \
   }
 
 #define SIMD_CHECK_FUNCTION(type)           \
     return *a;                              \
   }
 
-#define SIMD_EXTRACT_LANE_FUNCTION(type, lanes)               \
-  RUNTIME_FUNCTION(Runtime_##type##ExtractLane) {             \
-    HandleScope scope(isolate);                               \
-    DCHECK(args.length() == 2);                               \
-    CONVERT_ARG_HANDLE_CHECKED(type, a, 0);                   \
-    CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, lanes);            \
-    return *isolate->factory()->NewNumber(a->get_lane(lane)); \
+#define SIMD_EXTRACT_LANE_FUNCTION(type, lanes, extract_fn)    \
+  RUNTIME_FUNCTION(Runtime_##type##ExtractLane) {              \
+    HandleScope scope(isolate);                                \
+    DCHECK(args.length() == 2);                                \
+    CONVERT_ARG_HANDLE_CHECKED(type, a, 0);                    \
+    CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, lanes);             \
+    return *isolate->factory()->extract_fn(a->get_lane(lane)); \
   }
 
-#define SIMD4_EQUALS_FUNCTION(type)                          \
-  RUNTIME_FUNCTION(Runtime_##type##Equals) {                 \
-    HandleScope scope(isolate);                              \
-    DCHECK(args.length() == 2);                              \
-    CONVERT_ARG_HANDLE_CHECKED(type, a, 0);                  \
-    CONVERT_ARG_HANDLE_CHECKED(type, b, 1);                  \
-    return Equals(a->get_lane(0), b->get_lane(0)) &&         \
-                   Equals(a->get_lane(1), b->get_lane(1)) && \
-                   Equals(a->get_lane(2), b->get_lane(2)) && \
-                   Equals(a->get_lane(3), b->get_lane(3))    \
-               ? Smi::FromInt(EQUAL)                         \
-               : Smi::FromInt(NOT_EQUAL);                    \
+#define SIMD_REPLACE_NUMERIC_LANE_FUNCTION(type, lane_type, lane_count) \
+  RUNTIME_FUNCTION(Runtime_##type##ReplaceLane) {                       \
+    HandleScope scope(isolate);                                         \
+    DCHECK(args.length() == 3);                                         \
+    CONVERT_ARG_HANDLE_CHECKED(type, simd, 0);                          \
+    CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, lane_count);                 \
+    CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, 2);                       \
+    lane_type lanes[lane_count];                                        \
+    for (int i = 0; i < lane_count; i++) {                              \
+      lanes[i] = simd->get_lane(i);                                     \
+    }                                                                   \
+    lanes[lane] = ConvertNumber<lane_type>(number->Number());           \
+    Handle<type> result = isolate->factory()->New##type(lanes);         \
+    return *result;                                                     \
   }
 
-#define SIMD4_SAME_VALUE_FUNCTION(type)              \
-  RUNTIME_FUNCTION(Runtime_##type##SameValue) {      \
-    HandleScope scope(isolate);                      \
-    DCHECK(args.length() == 2);                      \
-    CONVERT_ARG_HANDLE_CHECKED(type, a, 0);          \
-    CONVERT_ARG_HANDLE_CHECKED(type, b, 1);          \
-    return isolate->heap()->ToBoolean(               \
-        SameValue(a->get_lane(0), b->get_lane(0)) && \
-        SameValue(a->get_lane(1), b->get_lane(1)) && \
-        SameValue(a->get_lane(2), b->get_lane(2)) && \
-        SameValue(a->get_lane(3), b->get_lane(3)));  \
+#define SIMD_REPLACE_BOOLEAN_LANE_FUNCTION(type, lane_count)    \
+  RUNTIME_FUNCTION(Runtime_##type##ReplaceLane) {               \
+    HandleScope scope(isolate);                                 \
+    DCHECK(args.length() == 3);                                 \
+    CONVERT_ARG_HANDLE_CHECKED(type, simd, 0);                  \
+    CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, lane_count);         \
+    bool lanes[lane_count];                                     \
+    for (int i = 0; i < lane_count; i++) {                      \
+      lanes[i] = simd->get_lane(i);                             \
+    }                                                           \
+    lanes[lane] = args[2]->BooleanValue();                      \
+    Handle<type> result = isolate->factory()->New##type(lanes); \
+    return *result;                                             \
   }
 
-#define SIMD4_SAME_VALUE_ZERO_FUNCTION(type)             \
-  RUNTIME_FUNCTION(Runtime_##type##SameValueZero) {      \
-    HandleScope scope(isolate);                          \
-    DCHECK(args.length() == 2);                          \
-    CONVERT_ARG_HANDLE_CHECKED(type, a, 0);              \
-    CONVERT_ARG_HANDLE_CHECKED(type, b, 1);              \
-    return isolate->heap()->ToBoolean(                   \
-        SameValueZero(a->get_lane(0), b->get_lane(0)) && \
-        SameValueZero(a->get_lane(1), b->get_lane(1)) && \
-        SameValueZero(a->get_lane(2), b->get_lane(2)) && \
-        SameValueZero(a->get_lane(3), b->get_lane(3)));  \
-  }
-
-#define SIMD4_EXTRACT_LANE_FUNCTION(type) SIMD_EXTRACT_LANE_FUNCTION(type, 4)
-
-#define SIMD4_FUNCTIONS(type)        \
-  SIMD4_CREATE_FUNCTION(type)        \
-  SIMD_CHECK_FUNCTION(type)          \
-  SIMD4_EXTRACT_LANE_FUNCTION(type)  \
-  SIMD4_EQUALS_FUNCTION(type)        \
-  SIMD4_SAME_VALUE_FUNCTION(type)    \
-  SIMD4_SAME_VALUE_ZERO_FUNCTION(type)
-
 
 namespace v8 {
 namespace internal {
 
 namespace {
 
-// Convert from Number object to float.
-inline float NumberToFloat(Object* number) {
-  return DoubleToFloat32(number->Number());
+// Functions to convert Numbers to SIMD component types.
+
+template <typename T>
+static T ConvertNumber(double number);
+
+
+template <>
+float ConvertNumber<float>(double number) {
+  return DoubleToFloat32(number);
+}
+
+
+template <>
+int32_t ConvertNumber<int32_t>(double number) {
+  return DoubleToInt32(number);
 }
 
 
-inline bool Equals(float x, float y) { return x == y; }
+template <>
+int16_t ConvertNumber<int16_t>(double number) {
+  return static_cast<int16_t>(DoubleToInt32(number));
+}
+
+
+template <>
+int8_t ConvertNumber<int8_t>(double number) {
+  return static_cast<int8_t>(DoubleToInt32(number));
+}
+
+
+bool Equals(Float32x4* a, Float32x4* b) {
+  for (int i = 0; i < 4; i++) {
+    if (a->get_lane(i) != b->get_lane(i)) return false;
+  }
+  return true;
+}
 
 }  // namespace
 
-SIMD4_FUNCTIONS(Float32x4)
 
+RUNTIME_FUNCTION(Runtime_IsSimdObject) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 1);
+  return isolate->heap()->ToBoolean(args[0]->IsSimd128Value());
+}
+
+
+RUNTIME_FUNCTION(Runtime_SimdToObject) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 1);
+  CONVERT_ARG_HANDLE_CHECKED(Simd128Value, value, 0);
+  return *Object::ToObject(isolate, value).ToHandleChecked();
+}
+
+
+RUNTIME_FUNCTION(Runtime_SimdEquals) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 2);
+  CONVERT_ARG_HANDLE_CHECKED(Simd128Value, a, 0);
+  bool result = false;
+  // args[1] is of unknown type.
+  if (args[1]->IsSimd128Value()) {
+    Simd128Value* b = Simd128Value::cast(args[1]);
+    if (a->map()->instance_type() == b->map()->instance_type()) {
+      if (a->IsFloat32x4()) {
+        result = Equals(Float32x4::cast(*a), Float32x4::cast(b));
+      } else {
+        result = a->BitwiseEquals(b);
+      }
+    }
+  }
+  return Smi::FromInt(result ? EQUAL : NOT_EQUAL);
+}
+
+
+RUNTIME_FUNCTION(Runtime_SimdSameValue) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 2);
+  CONVERT_ARG_HANDLE_CHECKED(Simd128Value, a, 0);
+  bool result = false;
+  // args[1] is of unknown type.
+  if (args[1]->IsSimd128Value()) {
+    Simd128Value* b = Simd128Value::cast(args[1]);
+    if (a->map()->instance_type() == b->map()->instance_type()) {
+      if (a->IsFloat32x4()) {
+        result = Float32x4::cast(*a)->SameValue(Float32x4::cast(b));
+      } else {
+        result = a->BitwiseEquals(b);
+      }
+    }
+  }
+  return isolate->heap()->ToBoolean(result);
+}
+
+
+RUNTIME_FUNCTION(Runtime_SimdSameValueZero) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 2);
+  CONVERT_ARG_HANDLE_CHECKED(Simd128Value, a, 0);
+  bool result = false;
+  // args[1] is of unknown type.
+  if (args[1]->IsSimd128Value()) {
+    Simd128Value* b = Simd128Value::cast(args[1]);
+    if (a->map()->instance_type() == b->map()->instance_type()) {
+      if (a->IsFloat32x4()) {
+        result = Float32x4::cast(*a)->SameValueZero(Float32x4::cast(b));
+      } else {
+        result = a->BitwiseEquals(b);
+      }
+    }
+  }
+  return isolate->heap()->ToBoolean(result);
+}
+
+
+SIMD_CREATE_NUMERIC_FUNCTION(Float32x4, float, 4)
+SIMD_CREATE_NUMERIC_FUNCTION(Int32x4, int32_t, 4)
+SIMD_CREATE_BOOLEAN_FUNCTION(Bool32x4, 4)
+SIMD_CREATE_NUMERIC_FUNCTION(Int16x8, int16_t, 8)
+SIMD_CREATE_BOOLEAN_FUNCTION(Bool16x8, 8)
+SIMD_CREATE_NUMERIC_FUNCTION(Int8x16, int8_t, 16)
+SIMD_CREATE_BOOLEAN_FUNCTION(Bool8x16, 16)
+
+
+SIMD_CHECK_FUNCTION(Float32x4)
+SIMD_CHECK_FUNCTION(Int32x4)
+SIMD_CHECK_FUNCTION(Bool32x4)
+SIMD_CHECK_FUNCTION(Int16x8)
+SIMD_CHECK_FUNCTION(Bool16x8)
+SIMD_CHECK_FUNCTION(Int8x16)
+SIMD_CHECK_FUNCTION(Bool8x16)
+
+
+SIMD_EXTRACT_LANE_FUNCTION(Float32x4, 4, NewNumber)
+SIMD_EXTRACT_LANE_FUNCTION(Int32x4, 4, NewNumber)
+SIMD_EXTRACT_LANE_FUNCTION(Bool32x4, 4, ToBoolean)
+SIMD_EXTRACT_LANE_FUNCTION(Int16x8, 8, NewNumber)
+SIMD_EXTRACT_LANE_FUNCTION(Bool16x8, 8, ToBoolean)
+SIMD_EXTRACT_LANE_FUNCTION(Int8x16, 16, NewNumber)
+SIMD_EXTRACT_LANE_FUNCTION(Bool8x16, 16, ToBoolean)
+
+
+RUNTIME_FUNCTION(Runtime_Int16x8UnsignedExtractLane) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 2);
+  CONVERT_ARG_HANDLE_CHECKED(Int16x8, a, 0);
+  CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, 8);
+  return *isolate->factory()->NewNumber(bit_cast<uint16_t>(a->get_lane(lane)));
+}
+
+
+RUNTIME_FUNCTION(Runtime_Int8x16UnsignedExtractLane) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 2);
+  CONVERT_ARG_HANDLE_CHECKED(Int8x16, a, 0);
+  CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, 16);
+  return *isolate->factory()->NewNumber(bit_cast<uint8_t>(a->get_lane(lane)));
+}
+
+
+SIMD_REPLACE_NUMERIC_LANE_FUNCTION(Float32x4, float, 4)
+SIMD_REPLACE_NUMERIC_LANE_FUNCTION(Int32x4, int32_t, 4)
+SIMD_REPLACE_BOOLEAN_LANE_FUNCTION(Bool32x4, 4)
+SIMD_REPLACE_NUMERIC_LANE_FUNCTION(Int16x8, int16_t, 8)
+SIMD_REPLACE_BOOLEAN_LANE_FUNCTION(Bool16x8, 8)
+SIMD_REPLACE_NUMERIC_LANE_FUNCTION(Int8x16, int8_t, 16)
+SIMD_REPLACE_BOOLEAN_LANE_FUNCTION(Bool8x16, 16)
 }  // namespace internal
 }  // namespace v8
index f89618dacfdad3fea604742ed5be3d7ab9f6bcc8..9c5c0b5f99fc497493a3818c65290624d6e6d194 100644 (file)
@@ -569,13 +569,42 @@ namespace internal {
   F(Arguments, 1, 1)
 
 
-#define FOR_EACH_INTRINSIC_SIMD(F) \
-  F(CreateFloat32x4, 4, 1)         \
-  F(Float32x4Check, 1, 1)          \
-  F(Float32x4ExtractLane, 2, 1)    \
-  F(Float32x4Equals, 2, 1)         \
-  F(Float32x4SameValue, 2, 1)      \
-  F(Float32x4SameValueZero, 2, 1)
+#define FOR_EACH_INTRINSIC_SIMD(F)    \
+  F(IsSimdObject, 1, 1)               \
+  F(SimdToObject, 1, 1)               \
+  F(SimdEquals, 2, 1)                 \
+  F(SimdSameValue, 2, 1)              \
+  F(SimdSameValueZero, 2, 1)          \
+  F(CreateFloat32x4, 4, 1)            \
+  F(CreateInt32x4, 4, 1)              \
+  F(CreateBool32x4, 4, 1)             \
+  F(CreateInt16x8, 8, 1)              \
+  F(CreateBool16x8, 8, 1)             \
+  F(CreateInt8x16, 16, 1)             \
+  F(CreateBool8x16, 16, 1)            \
+  F(Float32x4Check, 1, 1)             \
+  F(Int32x4Check, 1, 1)               \
+  F(Bool32x4Check, 1, 1)              \
+  F(Int16x8Check, 1, 1)               \
+  F(Bool16x8Check, 1, 1)              \
+  F(Int8x16Check, 1, 1)               \
+  F(Bool8x16Check, 1, 1)              \
+  F(Float32x4ExtractLane, 2, 1)       \
+  F(Int32x4ExtractLane, 2, 1)         \
+  F(Bool32x4ExtractLane, 2, 1)        \
+  F(Int16x8ExtractLane, 2, 1)         \
+  F(Int16x8UnsignedExtractLane, 2, 1) \
+  F(Bool16x8ExtractLane, 2, 1)        \
+  F(Int8x16ExtractLane, 2, 1)         \
+  F(Int8x16UnsignedExtractLane, 2, 1) \
+  F(Bool8x16ExtractLane, 2, 1)        \
+  F(Float32x4ReplaceLane, 3, 1)       \
+  F(Int32x4ReplaceLane, 3, 1)         \
+  F(Bool32x4ReplaceLane, 3, 1)        \
+  F(Int16x8ReplaceLane, 3, 1)         \
+  F(Bool16x8ReplaceLane, 3, 1)        \
+  F(Int8x16ReplaceLane, 3, 1)         \
+  F(Bool8x16ReplaceLane, 3, 1)
 
 
 #define FOR_EACH_INTRINSIC_STRINGS(F)           \
index 302ac01573b3322496227db85b6e77aab5cc36d5..0087b9f231f8e162eb09ee1387c276f2a14bd08d 100644 (file)
@@ -229,6 +229,12 @@ TypeImpl<Config>::BitsetType::Lub(i::Map* map) {
     case HEAP_NUMBER_TYPE:
       return kNumber & kTaggedPointer;
     case FLOAT32X4_TYPE:
+    case INT32X4_TYPE:
+    case BOOL32X4_TYPE:
+    case INT16X8_TYPE:
+    case BOOL16X8_TYPE:
+    case INT8X16_TYPE:
+    case BOOL8X16_TYPE:
       // TODO(bbudge): Add type bits for SIMD value types.
       return kAny;
     case JS_VALUE_TYPE:
index eeea4da21623acf917c94e510633a4d47c75d4ac..582c5769936947698217cf5fd5ef219ab7e919eb 100644 (file)
@@ -200,27 +200,6 @@ inline double Floor(double x) {
   return std::floor(x);
 }
 
-// Implements the ES5 SameValue operation for floating point types.
-// http://www.ecma-international.org/ecma-262/6.0/#sec-samevalue
-template <typename T>
-bool SameValue(T x, T y) {
-  // SameValue(NaN, NaN) is true.
-  if (x != y) return std::isnan(x) && std::isnan(y);
-  // SameValue(0, -0) is false.
-  if (std::signbit(x) != std::signbit(y)) return false;
-  return true;
-}
-
-
-// Implements the ES6 SameValueZero operation for floating point types.
-// http://www.ecma-international.org/ecma-262/6.0/#sec-samevaluezero
-template <typename T>
-bool SameValueZero(T x, T y) {
-  if (x != y) return std::isnan(x) && std::isnan(y);
-  // SameValueZero doesn't distinguish between 0 and -0.
-  return true;
-}
-
 
 // TODO(svenpanne) Clean up the whole power-of-2 mess.
 inline int32_t WhichPowerOf2Abs(int32_t x) {
index 3ab60c8d8cc64b61e5c1c05114690f536f90addd..4efbc69776309e74777544d691ae4ae883bd3187 100644 (file)
@@ -1565,6 +1565,7 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
            factory->heap_number_map());
     __ j(equal, &heap_number, Label::kNear);
     if (cc != equal) {
+      Label not_simd;
       __ movp(rcx, FieldOperand(rax, HeapObject::kMapOffset));
       __ movzxbl(rcx, FieldOperand(rcx, Map::kInstanceTypeOffset));
       // Call runtime on identical objects.  Otherwise return equal.
@@ -1574,8 +1575,11 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
       __ cmpb(rcx, Immediate(static_cast<uint8_t>(SYMBOL_TYPE)));
       __ j(equal, &runtime_call, Label::kFar);
       // Call runtime on identical SIMD values since we must throw a TypeError.
-      __ cmpb(rcx, Immediate(static_cast<uint8_t>(FLOAT32X4_TYPE)));
-      __ j(equal, &runtime_call, Label::kFar);
+      __ cmpb(rcx, Immediate(static_cast<uint8_t>(FIRST_SIMD_VALUE_TYPE)));
+      __ j(less, &not_simd, Label::kFar);
+      __ cmpb(rcx, Immediate(static_cast<uint8_t>(LAST_SIMD_VALUE_TYPE)));
+      __ j(less_equal, &runtime_call, Label::kFar);
+      __ bind(&not_simd);
       if (is_strong(strength())) {
         // We have already tested for smis and heap numbers, so if both
         // arguments are not strings we must proceed to the slow case.
index dea70b5c7ab4b3615e073b65731cb8f86a1a9854..0d875673d3719e36e140c547b69ec6cb0d4a885c 100644 (file)
@@ -2215,8 +2215,12 @@ void LCodeGen::DoBranch(LBranch* instr) {
 
       if (expected.Contains(ToBooleanStub::SIMD_VALUE)) {
         // SIMD value -> true.
-        __ CmpInstanceType(map, FLOAT32X4_TYPE);
-        __ j(equal, instr->TrueLabel(chunk_));
+        Label not_simd;
+        __ CmpInstanceType(map, FIRST_SIMD_VALUE_TYPE);
+        __ j(less, &not_simd, Label::kNear);
+        __ CmpInstanceType(map, LAST_SIMD_VALUE_TYPE);
+        __ j(less_equal, instr->TrueLabel(chunk_));
+        __ bind(&not_simd);
       }
 
       if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
@@ -5749,6 +5753,36 @@ Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
     __ CmpObjectType(input, FLOAT32X4_TYPE, input);
     final_branch_condition = equal;
 
+  } else if (String::Equals(type_name, factory->int32x4_string())) {
+    __ JumpIfSmi(input, false_label, false_distance);
+    __ CmpObjectType(input, INT32X4_TYPE, input);
+    final_branch_condition = equal;
+
+  } else if (String::Equals(type_name, factory->bool32x4_string())) {
+    __ JumpIfSmi(input, false_label, false_distance);
+    __ CmpObjectType(input, BOOL32X4_TYPE, input);
+    final_branch_condition = equal;
+
+  } else if (String::Equals(type_name, factory->int16x8_string())) {
+    __ JumpIfSmi(input, false_label, false_distance);
+    __ CmpObjectType(input, INT16X8_TYPE, input);
+    final_branch_condition = equal;
+
+  } else if (String::Equals(type_name, factory->bool16x8_string())) {
+    __ JumpIfSmi(input, false_label, false_distance);
+    __ CmpObjectType(input, BOOL16X8_TYPE, input);
+    final_branch_condition = equal;
+
+  } else if (String::Equals(type_name, factory->int8x16_string())) {
+    __ JumpIfSmi(input, false_label, false_distance);
+    __ CmpObjectType(input, INT8X16_TYPE, input);
+    final_branch_condition = equal;
+
+  } else if (String::Equals(type_name, factory->bool8x16_string())) {
+    __ JumpIfSmi(input, false_label, false_distance);
+    __ CmpObjectType(input, BOOL8X16_TYPE, input);
+    final_branch_condition = equal;
+
   } else {
     __ jmp(false_label, false_distance);
   }
index cdcbaf94027810275bc3d36a1de53bc61e9aa608..a9a777e499d9caa76b2403d39ce330be7a6e067b 100644 (file)
@@ -1389,6 +1389,7 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
            Immediate(isolate()->factory()->heap_number_map()));
     __ j(equal, &generic_heap_number_comparison, Label::kNear);
     if (cc != equal) {
+      Label not_simd;
       __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
       __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
       // Call runtime on identical JSObjects.  Otherwise return equal.
@@ -1398,8 +1399,11 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
       __ cmpb(ecx, static_cast<uint8_t>(SYMBOL_TYPE));
       __ j(equal, &runtime_call, Label::kFar);
       // Call runtime on identical SIMD values since we must throw a TypeError.
-      __ cmpb(ecx, static_cast<uint8_t>(FLOAT32X4_TYPE));
-      __ j(equal, &runtime_call, Label::kFar);
+      __ cmpb(ecx, static_cast<uint8_t>(FIRST_SIMD_VALUE_TYPE));
+      __ j(less, &not_simd, Label::kFar);
+      __ cmpb(ecx, static_cast<uint8_t>(LAST_SIMD_VALUE_TYPE));
+      __ j(less_equal, &runtime_call, Label::kFar);
+      __ bind(&not_simd);
       if (is_strong(strength())) {
         // We have already tested for smis and heap numbers, so if both
         // arguments are not strings we must proceed to the slow case.
index b88e29c6cf215b194c12c0ce2eccc0c5d81115be..13ebfc8b6913004b8f9888b230bde88ed860debb 100644 (file)
@@ -2440,8 +2440,12 @@ void LCodeGen::DoBranch(LBranch* instr) {
 
       if (expected.Contains(ToBooleanStub::SIMD_VALUE)) {
         // SIMD value -> true.
-        __ CmpInstanceType(map, FLOAT32X4_TYPE);
-        __ j(equal, instr->TrueLabel(chunk_));
+        Label not_simd;
+        __ CmpInstanceType(map, FIRST_SIMD_VALUE_TYPE);
+        __ j(less, &not_simd, Label::kNear);
+        __ CmpInstanceType(map, LAST_SIMD_VALUE_TYPE);
+        __ j(less_equal, instr->TrueLabel(chunk_));
+        __ bind(&not_simd);
       }
 
       if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
@@ -6155,6 +6159,36 @@ Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
     __ CmpObjectType(input, FLOAT32X4_TYPE, input);
     final_branch_condition = equal;
 
+  } else if (String::Equals(type_name, factory()->int32x4_string())) {
+    __ JumpIfSmi(input, false_label, false_distance);
+    __ CmpObjectType(input, INT32X4_TYPE, input);
+    final_branch_condition = equal;
+
+  } else if (String::Equals(type_name, factory()->bool32x4_string())) {
+    __ JumpIfSmi(input, false_label, false_distance);
+    __ CmpObjectType(input, BOOL32X4_TYPE, input);
+    final_branch_condition = equal;
+
+  } else if (String::Equals(type_name, factory()->int16x8_string())) {
+    __ JumpIfSmi(input, false_label, false_distance);
+    __ CmpObjectType(input, INT16X8_TYPE, input);
+    final_branch_condition = equal;
+
+  } else if (String::Equals(type_name, factory()->bool16x8_string())) {
+    __ JumpIfSmi(input, false_label, false_distance);
+    __ CmpObjectType(input, BOOL16X8_TYPE, input);
+    final_branch_condition = equal;
+
+  } else if (String::Equals(type_name, factory()->int8x16_string())) {
+    __ JumpIfSmi(input, false_label, false_distance);
+    __ CmpObjectType(input, INT8X16_TYPE, input);
+    final_branch_condition = equal;
+
+  } else if (String::Equals(type_name, factory()->bool8x16_string())) {
+    __ JumpIfSmi(input, false_label, false_distance);
+    __ CmpObjectType(input, BOOL8X16_TYPE, input);
+    final_branch_condition = equal;
+
   } else {
     __ jmp(false_label, false_distance);
   }
index 4f6813778561f0fc0905749d87fc861fb55c4199..1994e9bb8c697ca00dd217b14d85fbd16d0ac1a2 100644 (file)
@@ -482,20 +482,31 @@ TEST(HeapSnapshotSymbol) {
 }
 
 
-TEST(HeapSnapshotFloat32x4) {
+void CheckSimdSnapshot(const char* program, const char* var_name) {
   i::FLAG_harmony_simd = true;
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
   v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
 
-  CompileRun("a = SIMD.Float32x4(1, 2, 3, 4);\n");
+  CompileRun(program);
   const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
   CHECK(ValidateSnapshot(snapshot));
   const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
-  const v8::HeapGraphNode* a =
-      GetProperty(global, v8::HeapGraphEdge::kProperty, "a");
-  CHECK(a);
-  CHECK_EQ(a->GetType(), v8::HeapGraphNode::kSimdValue);
+  const v8::HeapGraphNode* var =
+      GetProperty(global, v8::HeapGraphEdge::kProperty, var_name);
+  CHECK(var);
+  CHECK_EQ(var->GetType(), v8::HeapGraphNode::kSimdValue);
+}
+
+
+TEST(HeapSnapshotSimd) {
+  CheckSimdSnapshot("a = SIMD.Float32x4();\n", "a");
+  CheckSimdSnapshot("a = SIMD.Int32x4();\n", "a");
+  CheckSimdSnapshot("a = SIMD.Bool32x4();\n", "a");
+  CheckSimdSnapshot("a = SIMD.Int16x8();\n", "a");
+  CheckSimdSnapshot("a = SIMD.Bool16x8();\n", "a");
+  CheckSimdSnapshot("a = SIMD.Int8x16();\n", "a");
+  CheckSimdSnapshot("a = SIMD.Bool8x16();\n", "a");
 }
 
 
index 87978c0d78f7b602d16b77e90b65432c52499a34..c54d67aeeb32f100a391369a10625be93b39d665 100644 (file)
@@ -215,20 +215,24 @@ TEST(HeapObjects) {
 
 
 template <typename T, typename LANE_TYPE, int LANES>
-static void CheckSimdLanes(T* value) {
-  // Get the original values, and check that all lanes can be set to new values
-  // without disturbing the other lanes.
-  LANE_TYPE lane_values[LANES];
+static void CheckSimdValue(T* value, LANE_TYPE lane_values[LANES],
+                           LANE_TYPE other_value) {
+  // Check against lane_values, and check that all lanes can be set to
+  // other_value without disturbing the other lanes.
   for (int i = 0; i < LANES; i++) {
-    lane_values[i] = value->get_lane(i);
+    CHECK_EQ(lane_values[i], value->get_lane(i));
   }
   for (int i = 0; i < LANES; i++) {
-    lane_values[i] += 1;
-    value->set_lane(i, lane_values[i]);
+    value->set_lane(i, other_value);  // change the value
     for (int j = 0; j < LANES; j++) {
-      CHECK_EQ(lane_values[j], value->get_lane(j));
+      if (i != j)
+        CHECK_EQ(lane_values[j], value->get_lane(j));
+      else
+        CHECK_EQ(other_value, value->get_lane(j));
     }
+    value->set_lane(i, lane_values[i]);  // restore the lane
   }
+  CHECK(value->BooleanValue());  // SIMD values are 'true'.
 }
 
 
@@ -239,42 +243,131 @@ TEST(SimdObjects) {
 
   HandleScope sc(isolate);
 
-  Handle<Float32x4> value = factory->NewFloat32x4(1, 2, 3, 4);
-  CHECK(value->IsFloat32x4());
-  CHECK(value->BooleanValue());  // SIMD values map to true.
-  CHECK_EQ(value->get_lane(0), 1);
-  CHECK_EQ(value->get_lane(1), 2);
-  CHECK_EQ(value->get_lane(2), 3);
-  CHECK_EQ(value->get_lane(3), 4);
-
-  CheckSimdLanes<Float32x4, float, 4>(*value);
-
-  // Check all lanes, and special lane values.
-  value->set_lane(0, 0);
-  CHECK_EQ(0, value->get_lane(0));
-  value->set_lane(1, -0.0);
-  CHECK_EQ(-0.0, value->get_lane(1));
-  CHECK(std::signbit(value->get_lane(1)));  // Sign bit is preserved.
-  float quiet_NaN = std::numeric_limits<float>::quiet_NaN();
-  float signaling_NaN = std::numeric_limits<float>::signaling_NaN();
-  value->set_lane(2, quiet_NaN);
-  CHECK(std::isnan(value->get_lane(2)));
-  value->set_lane(3, signaling_NaN);
-  CHECK(std::isnan(value->get_lane(3)));
-
-  // Check SIMD value printing.
+  // Float32x4
   {
-    value = factory->NewFloat32x4(1, 2, 3, 4);
+    float lanes[4] = {1, 2, 3, 4};
+    float quiet_NaN = std::numeric_limits<float>::quiet_NaN();
+    float signaling_NaN = std::numeric_limits<float>::signaling_NaN();
+
+    Handle<Float32x4> value = factory->NewFloat32x4(lanes);
+    CHECK(value->IsFloat32x4());
+    CheckSimdValue<Float32x4, float, 4>(*value, lanes, 3.14f);
+
+    // Check special lane values.
+    value->set_lane(1, -0.0);
+    CHECK_EQ(-0.0, value->get_lane(1));
+    CHECK(std::signbit(value->get_lane(1)));  // Sign bit should be preserved.
+    value->set_lane(2, quiet_NaN);
+    CHECK(std::isnan(value->get_lane(2)));
+    value->set_lane(3, signaling_NaN);
+    CHECK(std::isnan(value->get_lane(3)));
+
+#ifdef OBJECT_PRINT
+    // Check value printing.
+    {
+      value = factory->NewFloat32x4(lanes);
+      std::ostringstream os;
+      value->Float32x4Print(os);
+      CHECK_EQ("1, 2, 3, 4", os.str());
+    }
+    {
+      float special_lanes[4] = {0, -0.0, quiet_NaN, signaling_NaN};
+      value = factory->NewFloat32x4(special_lanes);
+      std::ostringstream os;
+      value->Float32x4Print(os);
+      // Value printing doesn't preserve signed zeroes.
+      CHECK_EQ("0, 0, NaN, NaN", os.str());
+    }
+#endif  // OBJECT_PRINT
+  }
+  // Int32x4
+  {
+    int32_t lanes[4] = {-1, 0, 1, 2};
+
+    Handle<Int32x4> value = factory->NewInt32x4(lanes);
+    CHECK(value->IsInt32x4());
+    CheckSimdValue<Int32x4, int32_t, 4>(*value, lanes, 3);
+
+#ifdef OBJECT_PRINT
     std::ostringstream os;
-    value->Float32x4Print(os);
-    CHECK_EQ("1, 2, 3, 4", os.str());
+    value->Int32x4Print(os);
+    CHECK_EQ("-1, 0, 1, 2", os.str());
+#endif  // OBJECT_PRINT
   }
+  // Bool32x4
   {
-    value = factory->NewFloat32x4(0, -0.0, quiet_NaN, signaling_NaN);
+    bool lanes[4] = {true, true, true, false};
+
+    Handle<Bool32x4> value = factory->NewBool32x4(lanes);
+    CHECK(value->IsBool32x4());
+    CheckSimdValue<Bool32x4, bool, 4>(*value, lanes, false);
+
+#ifdef OBJECT_PRINT
+    std::ostringstream os;
+    value->Bool32x4Print(os);
+    CHECK_EQ("true, true, true, false", os.str());
+#endif  // OBJECT_PRINT
+  }
+  // Int16x8
+  {
+    int16_t lanes[8] = {-1, 0, 1, 2, 3, 4, 5, -32768};
+
+    Handle<Int16x8> value = factory->NewInt16x8(lanes);
+    CHECK(value->IsInt16x8());
+    CheckSimdValue<Int16x8, int16_t, 8>(*value, lanes, 32767);
+
+#ifdef OBJECT_PRINT
     std::ostringstream os;
-    value->Float32x4Print(os);
-    // Value printing doesn't preserve signed zeroes.
-    CHECK_EQ("0, 0, NaN, NaN", os.str());
+    value->Int16x8Print(os);
+    CHECK_EQ("-1, 0, 1, 2, 3, 4, 5, -32768", os.str());
+#endif  // OBJECT_PRINT
+  }
+  // Bool16x8
+  {
+    bool lanes[8] = {true, true, true, true, true, true, true, false};
+
+    Handle<Bool16x8> value = factory->NewBool16x8(lanes);
+    CHECK(value->IsBool16x8());
+    CheckSimdValue<Bool16x8, bool, 8>(*value, lanes, false);
+
+#ifdef OBJECT_PRINT
+    std::ostringstream os;
+    value->Bool16x8Print(os);
+    CHECK_EQ("true, true, true, true, true, true, true, false", os.str());
+#endif  // OBJECT_PRINT
+  }
+  // Int8x16
+  {
+    int8_t lanes[16] = {-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, -128};
+
+    Handle<Int8x16> value = factory->NewInt8x16(lanes);
+    CHECK(value->IsInt8x16());
+    CheckSimdValue<Int8x16, int8_t, 16>(*value, lanes, 127);
+
+#ifdef OBJECT_PRINT
+    std::ostringstream os;
+    value->Int8x16Print(os);
+    CHECK_EQ("-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, -128",
+             os.str());
+#endif  // OBJECT_PRINT
+  }
+  // Bool8x16
+  {
+    bool lanes[16] = {true, true, true, true, true, true, true, false,
+                      true, true, true, true, true, true, true, false};
+
+    Handle<Bool8x16> value = factory->NewBool8x16(lanes);
+    CHECK(value->IsBool8x16());
+    CheckSimdValue<Bool8x16, bool, 16>(*value, lanes, false);
+
+#ifdef OBJECT_PRINT
+    std::ostringstream os;
+    value->Bool8x16Print(os);
+    CHECK_EQ(
+        "true, true, true, true, true, true, true, false, true, true, true, "
+        "true, true, true, true, false",
+        os.str());
+#endif  // OBJECT_PRINT
   }
 }
 
index e87032df8f9640520655f5fba2d572c241f2642c..fd72b695ee0d62f91f65cc760d0d52dc09fe4319 100644 (file)
 
 using namespace v8::internal;
 
+#define FLOAT_TEST(type, lane_count)                     \
+  {                                                      \
+    float nan = std::numeric_limits<float>::quiet_NaN(); \
+    float lanes[lane_count] = {0};                       \
+    Handle<type> a = factory->New##type(lanes);          \
+    Handle<type> b = factory->New##type(lanes);          \
+    CHECK(a->BitwiseEquals(*b));                         \
+    CHECK(a->SameValue(*b));                             \
+    CHECK(a->SameValueZero(*b));                         \
+    CHECK_EQ(a->Hash(), b->Hash());                      \
+    for (int i = 0; i < lane_count; i++) {               \
+      a->set_lane(i, -0.0);                              \
+      CHECK(!a->BitwiseEquals(*b));                      \
+      CHECK_NE(a->Hash(), b->Hash());                    \
+      CHECK(!a->SameValue(*b));                          \
+      CHECK(a->SameValueZero(*b));                       \
+      b->set_lane(i, -0.0);                              \
+      CHECK(a->BitwiseEquals(*b));                       \
+      CHECK_EQ(a->Hash(), b->Hash());                    \
+      CHECK(a->SameValue(*b));                           \
+      CHECK(a->SameValueZero(*b));                       \
+      a->set_lane(i, nan);                               \
+      CHECK(!a->BitwiseEquals(*b));                      \
+      CHECK(!a->SameValue(*b));                          \
+      CHECK(!a->SameValueZero(*b));                      \
+      CHECK_NE(a->Hash(), b->Hash());                    \
+      b->set_lane(i, nan);                               \
+      CHECK(a->BitwiseEquals(*b));                       \
+      CHECK_EQ(a->Hash(), b->Hash());                    \
+      CHECK(a->SameValue(*b));                           \
+      CHECK(a->SameValueZero(*b));                       \
+    }                                                    \
+  }
+
+#define INT_TEST(type, lane_count, lane_type)   \
+  {                                             \
+    lane_type lanes[lane_count] = {0};          \
+    Handle<type> a = factory->New##type(lanes); \
+    Handle<type> b = factory->New##type(lanes); \
+    CHECK(a->BitwiseEquals(*b));                \
+    CHECK(a->SameValue(*b));                    \
+    CHECK(a->SameValueZero(*b));                \
+    CHECK_EQ(a->Hash(), b->Hash());             \
+    for (int i = 0; i < lane_count; i++) {      \
+      a->set_lane(i, i + 1);                    \
+      CHECK(!a->BitwiseEquals(*b));             \
+      CHECK_NE(a->Hash(), b->Hash());           \
+      CHECK(!a->SameValue(*b));                 \
+      CHECK(!a->SameValueZero(*b));             \
+      b->set_lane(i, i + 1);                    \
+      CHECK(a->BitwiseEquals(*b));              \
+      CHECK_EQ(a->Hash(), b->Hash());           \
+      CHECK(a->SameValue(*b));                  \
+      CHECK(a->SameValueZero(*b));              \
+      a->set_lane(i, -(i + 1));                 \
+      CHECK(!a->BitwiseEquals(*b));             \
+      CHECK_NE(a->Hash(), b->Hash());           \
+      CHECK(!a->SameValue(*b));                 \
+      CHECK(!a->SameValueZero(*b));             \
+      b->set_lane(i, -(i + 1));                 \
+      CHECK(a->BitwiseEquals(*b));              \
+      CHECK_EQ(a->Hash(), b->Hash());           \
+      CHECK(a->SameValue(*b));                  \
+      CHECK(a->SameValueZero(*b));              \
+    }                                           \
+  }
 
-TEST(SameValue) {
+#define BOOL_TEST(type, lane_count)             \
+  {                                             \
+    bool lanes[lane_count] = {false};           \
+    Handle<type> a = factory->New##type(lanes); \
+    Handle<type> b = factory->New##type(lanes); \
+    CHECK(a->BitwiseEquals(*b));                \
+    CHECK(a->SameValue(*b));                    \
+    CHECK(a->SameValueZero(*b));                \
+    CHECK_EQ(a->Hash(), b->Hash());             \
+    for (int i = 0; i < lane_count; i++) {      \
+      a->set_lane(i, true);                     \
+      CHECK(!a->BitwiseEquals(*b));             \
+      CHECK_NE(a->Hash(), b->Hash());           \
+      CHECK(!a->SameValue(*b));                 \
+      CHECK(!a->SameValueZero(*b));             \
+      b->set_lane(i, true);                     \
+      CHECK(a->BitwiseEquals(*b));              \
+      CHECK_EQ(a->Hash(), b->Hash());           \
+      CHECK(a->SameValue(*b));                  \
+      CHECK(a->SameValueZero(*b));              \
+    }                                           \
+  }
+
+TEST(SimdTypes) {
   CcTest::InitializeVM();
   Isolate* isolate = CcTest::i_isolate();
   Factory* factory = isolate->factory();
 
   HandleScope sc(isolate);
 
-  float nan = std::numeric_limits<float>::quiet_NaN();
-
-  Handle<Float32x4> a = factory->NewFloat32x4(0, 0, 0, 0);
-  Handle<Float32x4> b = factory->NewFloat32x4(0, 0, 0, 0);
-  CHECK(a->SameValue(*b));
-  for (int i = 0; i < 4; i++) {
-    a->set_lane(i, nan);
-    CHECK(!a->SameValue(*b));
-    CHECK(!a->SameValueZero(*b));
-    b->set_lane(i, nan);
-    CHECK(a->SameValue(*b));
-    CHECK(a->SameValueZero(*b));
-    a->set_lane(i, -0.0);
-    CHECK(!a->SameValue(*b));
-    b->set_lane(i, 0);
-    CHECK(!a->SameValue(*b));
-    CHECK(a->SameValueZero(*b));
-    b->set_lane(i, -0.0);
-    CHECK(a->SameValue(*b));
-    CHECK(a->SameValueZero(*b));
-
-    a->set_lane(i, 0);
-    b->set_lane(i, 0);
-  }
+  FLOAT_TEST(Float32x4, 4)
+  INT_TEST(Int32x4, 4, int32_t)
+  BOOL_TEST(Bool32x4, 4)
+  INT_TEST(Int16x8, 8, int16_t)
+  BOOL_TEST(Bool16x8, 8)
+  INT_TEST(Int8x16, 16, int8_t)
+  BOOL_TEST(Bool8x16, 16)
 }
index 941eff8034358b140ba44f70839e3d89c49f1a2d..0c52072646c7ede235b46cf6ebe0ed20ae146595 100644 (file)
@@ -8,7 +8,17 @@
 function lanesForType(typeName) {
   // The lane count follows the first 'x' in the type name, which begins with
   // 'float', 'int', or 'bool'.
-  return Number.parseInt(typeName[typeName.indexOf('x') + 1]);
+  return Number.parseInt(typeName.substr(typeName.indexOf('x') + 1));
+}
+
+
+// Creates an instance that has been zeroed, so it can be used for equality
+// testing.
+function createInstance(type) {
+  // Provide enough parameters for the longest type (currently 16). It's
+  // important that instances be consistent to better test that different SIMD
+  // types can't be compared and are never equal or the same in any sense.
+  return SIMD[type](0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
 }
 
 
@@ -35,278 +45,404 @@ function isValidSimdString(string, value, type, lanes) {
 }
 
 
-// Test for structural equivalence.
-function areEquivalent(type, lanes, a, b) {
-  var simdFn = SIMD[type];
-  for (var i = 0; i < lanes; i++) {
-    if (simdFn.extractLane(a, i) !== simdFn.extractLane(b, i))
-      return false;
-  }
-  return true;
-}
-
-
-var sameValue = natives.$sameValue;
-var sameValueZero = natives.$sameValueZero;
-
-// Calls SameValue and SameValueZero and checks that their results match. Also
-// checks the internal SameValue checks using Object freeze and defineProperty.
-function sameValueBoth(a, b) {
-  var result = sameValue(a, b);
-  assertTrue(result === sameValueZero(a, b));
-  return result;
-}
-
-
-// Calls SameValue and SameValueZero and checks that their results don't match.
-function sameValueZeroOnly(a, b) {
-  var result = sameValueZero(a, b);
-  assertTrue(result && !sameValue(a, b));
-  return result;
-}
+var simdTypeNames = ['Float32x4', 'Int32x4', 'Bool32x4',
+                                  'Int16x8', 'Bool16x8',
+                                  'Int8x16', 'Bool8x16'];
 
+var nonSimdValues = [347, 1.275, NaN, "string", null, undefined, {},
+                     function() {}];
 
-// Tests for the global SIMD object.
-function TestSIMDObject() {
-  assertSame(typeof SIMD, 'object');
-  assertSame(SIMD.constructor, Object);
-  assertSame(Object.getPrototypeOf(SIMD), Object.prototype);
-  assertSame(SIMD + "", "[object SIMD]");
+function checkTypeMatrix(type, fn) {
+  // Check against non-SIMD types.
+  nonSimdValues.forEach(fn);
+  // Check against SIMD values of a different type.
+  for (var i = 0; i < simdTypeNames.length; i++) {
+    var otherType = simdTypeNames[i];
+    if (type != otherType) fn(createInstance(otherType));
+  }
 }
-TestSIMDObject()
 
-// TestConstructor populates this with interesting values for the other tests.
-var values;
 
-// Test different forms of constructor calls. This test populates 'values' with
-// a variety of SIMD values as a side effect, which are used by other tests.
+// Test different forms of constructor calls.
 function TestConstructor(type, lanes) {
   var simdFn = SIMD[type];
+  var instance = createInstance(type);
+
   assertFalse(Object === simdFn.prototype.constructor)
   assertFalse(simdFn === Object.prototype.constructor)
   assertSame(simdFn, simdFn.prototype.constructor)
 
-  values = []
-
-  // The constructor expects values for all lanes.
-  switch (type) {
-    case 'Float32x4':
-      // The constructor expects values for all lanes.
-      assertThrows(function () { simdFn() }, TypeError)
-      assertThrows(function () { simdFn(0) }, TypeError)
-      assertThrows(function () { simdFn(0, 1) }, TypeError)
-      assertThrows(function () { simdFn(0, 1, 2) }, TypeError)
-
-      values.push(simdFn(1, 2, 3, 4))
-      values.push(simdFn(1, 2, 3, 4))       // test structural equivalence
-      values.push(simdFn(-0, NaN, 0, 0.5))
-      values.push(simdFn(-0, NaN, 0, 0.5))  // test structural equivalence
-      values.push(simdFn(3, 2, 1, 0))
-      values.push(simdFn(0, 0, 0, 0))
-      break
-  }
-  for (var i in values) {
-    assertSame(simdFn, values[i].__proto__.constructor)
-    assertSame(simdFn, Object(values[i]).__proto__.constructor)
-    assertSame(simdFn.prototype, values[i].__proto__)
-    assertSame(simdFn.prototype, Object(values[i]).__proto__)
-  }
+  assertSame(simdFn, instance.__proto__.constructor)
+  assertSame(simdFn, Object(instance).__proto__.constructor)
+  assertSame(simdFn.prototype, instance.__proto__)
+  assertSame(simdFn.prototype, Object(instance).__proto__)
 }
 
 
 function TestType(type, lanes) {
+  var simdFn = SIMD[type];
+  var instance = createInstance(type);
   var typeofString = type.charAt(0).toLowerCase() + type.slice(1);
-  for (var i in values) {
-    assertEquals(typeofString, typeof values[i])
-    assertTrue(typeof values[i] === typeofString)
-    assertTrue(typeof Object(values[i]) === 'object')
-    assertEquals(null, %_ClassOf(values[i]))
-    assertEquals(type, %_ClassOf(Object(values[i])))
-  }
+
+  assertEquals(typeofString, typeof instance)
+  assertTrue(typeof instance === typeofString)
+  assertTrue(typeof Object(instance) === 'object')
+  assertEquals(null, %_ClassOf(instance))
+  assertEquals(type, %_ClassOf(Object(instance)))
 }
 
 
 function TestPrototype(type, lanes) {
   var simdFn = SIMD[type];
+  var instance = createInstance(type);
+
   assertSame(Object.prototype, simdFn.prototype.__proto__)
-  for (var i in values) {
-    assertSame(simdFn.prototype, values[i].__proto__)
-    assertSame(simdFn.prototype, Object(values[i]).__proto__)
-  }
+  assertSame(simdFn.prototype, instance.__proto__)
+  assertSame(simdFn.prototype, Object(instance).__proto__)
 }
 
 
 function TestValueOf(type, lanes) {
   var simdFn = SIMD[type];
-  for (var i in values) {
-    assertTrue(values[i] === Object(values[i]).valueOf())
-    assertTrue(values[i] === values[i].valueOf())
-    assertTrue(simdFn.prototype.valueOf.call(Object(values[i])) === values[i])
-    assertTrue(simdFn.prototype.valueOf.call(values[i]) === values[i])
-  }
+  var instance = createInstance(type);
+
+  assertTrue(instance === Object(instance).valueOf())
+  assertTrue(instance === instance.valueOf())
+  assertTrue(simdFn.prototype.valueOf.call(Object(instance)) === instance)
+  assertTrue(simdFn.prototype.valueOf.call(instance) === instance)
 }
 
 
 function TestGet(type, lanes) {
   var simdFn = SIMD[type];
-  for (var i in values) {
-    assertEquals(undefined, values[i].a)
-    assertEquals(undefined, values[i]["a" + "b"])
-    assertEquals(undefined, values[i]["" + "1"])
-    assertEquals(undefined, values[i][42])
-  }
+  var instance = createInstance(type);
+
+  assertEquals(undefined, instance.a)
+  assertEquals(undefined, instance["a" + "b"])
+  assertEquals(undefined, instance["" + "1"])
+  assertEquals(undefined, instance[42])
 }
 
 
 function TestToBoolean(type, lanes) {
-  for (var i in values) {
-    assertTrue(Boolean(Object(values[i])))
-    assertFalse(!Object(values[i]))
-    assertTrue(Boolean(values[i]).valueOf())
-    assertFalse(!values[i])
-    assertTrue(!!values[i])
-    assertTrue(values[i] && true)
-    assertFalse(!values[i] && false)
-    assertTrue(!values[i] || true)
-    assertEquals(1, values[i] ? 1 : 2)
-    assertEquals(2, !values[i] ? 1 : 2)
-    if (!values[i]) assertUnreachable();
-    if (values[i]) {} else assertUnreachable();
-  }
+  var simdFn = SIMD[type];
+  var instance = createInstance(type);
+
+  assertTrue(Boolean(Object(instance)))
+  assertFalse(!Object(instance))
+  assertTrue(Boolean(instance).valueOf())
+  assertFalse(!instance)
+  assertTrue(!!instance)
+  assertTrue(instance && true)
+  assertFalse(!instance && false)
+  assertTrue(!instance || true)
+  assertEquals(1, instance ? 1 : 2)
+  assertEquals(2, !instance ? 1 : 2)
+  if (!instance) assertUnreachable();
+  if (instance) {} else assertUnreachable();
 }
 
 
 function TestToString(type, lanes) {
   var simdFn = SIMD[type];
-  for (var i in values) {
-    assertEquals(values[i].toString(), String(values[i]))
-    assertTrue(isValidSimdString(values[i].toString(), values[i], type, lanes))
-    assertTrue(
-        isValidSimdString(Object(values[i]).toString(), values[i], type, lanes))
-    assertTrue(isValidSimdString(
-        simdFn.prototype.toString.call(values[i]), values[i], type, lanes))
-  }
+  var instance = createInstance(type);
+
+  assertEquals(instance.toString(), String(instance))
+  assertTrue(isValidSimdString(instance.toString(), instance, type, lanes))
+  assertTrue(
+      isValidSimdString(Object(instance).toString(), instance, type, lanes))
+  assertTrue(isValidSimdString(
+      simdFn.prototype.toString.call(instance), instance, type, lanes))
 }
 
 
 function TestToNumber(type, lanes) {
-  for (var i in values) {
-    assertThrows(function() { Number(Object(values[i])) }, TypeError)
-    assertThrows(function() { +Object(values[i]) }, TypeError)
-    assertThrows(function() { Number(values[i]) }, TypeError)
-    assertThrows(function() { values[i] + 0 }, TypeError)
+  var simdFn = SIMD[type];
+  var instance = createInstance(type);
+
+  assertThrows(function() { Number(Object(instance)) }, TypeError)
+  assertThrows(function() { +Object(instance) }, TypeError)
+  assertThrows(function() { Number(instance) }, TypeError)
+  assertThrows(function() { instance + 0 }, TypeError)
+}
+
+
+function TestCoercions(type, lanes) {
+  var simdFn = SIMD[type];
+  var instance = createInstance(type);
+  // Test that setting a lane to value 'a' results in a lane with value 'b'.
+  function test(a, b) {
+    for (var i = 0; i < lanes; i++) {
+      var ainstance = simdFn.replaceLane(instance, i, a);
+      var lane_value = simdFn.extractLane(ainstance, i);
+      assertSame(b, lane_value);
+    }
+  }
+
+  switch (type) {
+    case 'Float32x4':
+      test(0, 0);
+      test(-0, -0);
+      test(NaN, NaN);
+      test(null, 0);
+      test(undefined, NaN);
+      test("5.25", 5.25);
+      test(Number.MAX_VALUE, Infinity);
+      test(-Number.MAX_VALUE, -Infinity);
+      test(Number.MIN_VALUE, 0);
+      break;
+    case 'Int32x4':
+      test(Infinity, 0);
+      test(-Infinity, 0);
+      test(NaN, 0);
+      test(0, 0);
+      test(-0, 0);
+      test(Number.MIN_VALUE, 0);
+      test(-Number.MIN_VALUE, 0);
+      test(0.1, 0);
+      test(-0.1, 0);
+      test(1, 1);
+      test(1.1, 1);
+      test(-1, -1);
+      test(-1.6, -1);
+      test(2147483647, 2147483647);
+      test(2147483648, -2147483648);
+      test(2147483649, -2147483647);
+      test(4294967295, -1);
+      test(4294967296, 0);
+      test(4294967297, 1);
+      break;
+    case 'Int16x8':
+      test(Infinity, 0);
+      test(-Infinity, 0);
+      test(NaN, 0);
+      test(0, 0);
+      test(-0, 0);
+      test(Number.MIN_VALUE, 0);
+      test(-Number.MIN_VALUE, 0);
+      test(0.1, 0);
+      test(-0.1, 0);
+      test(1, 1);
+      test(1.1, 1);
+      test(-1, -1);
+      test(-1.6, -1);
+      test(32767, 32767);
+      test(32768, -32768);
+      test(32769, -32767);
+      test(65535, -1);
+      test(65536, 0);
+      test(65537, 1);
+      break;
+    case 'Int8x16':
+      test(Infinity, 0);
+      test(-Infinity, 0);
+      test(NaN, 0);
+      test(0, 0);
+      test(-0, 0);
+      test(Number.MIN_VALUE, 0);
+      test(-Number.MIN_VALUE, 0);
+      test(0.1, 0);
+      test(-0.1, 0);
+      test(1, 1);
+      test(1.1, 1);
+      test(-1, -1);
+      test(-1.6, -1);
+      test(127, 127);
+      test(128, -128);
+      test(129, -127);
+      test(255, -1);
+      test(256, 0);
+      test(257, 1);
+      break;
+    case 'Bool32x4':
+    case 'Bool16x8':
+    case 'Bool8x16':
+      test(true, true);
+      test(false, false);
+      test(0, false);
+      test(1, true);
+      test(0.1, true);
+      test(NaN, false);
+      test(null, false);
+      test("", false);
+      test("false", true);
+      break;
   }
 }
 
 
 function TestEquality(type, lanes) {
+  var simdFn = SIMD[type];
+  var instance = createInstance(type);
+
   // Every SIMD value should equal itself, and non-strictly equal its wrapper.
-  for (var i in values) {
-    assertSame(values[i], values[i])
-    assertEquals(values[i], values[i])
-    assertTrue(Object.is(values[i], values[i]))
-    assertTrue(values[i] === values[i])
-    assertTrue(values[i] == values[i])
-    assertFalse(values[i] === Object(values[i]))
-    assertFalse(Object(values[i]) === values[i])
-    assertFalse(values[i] == Object(values[i]))
-    assertFalse(Object(values[i]) == values[i])
-    assertTrue(values[i] === values[i].valueOf())
-    assertTrue(values[i].valueOf() === values[i])
-    assertTrue(values[i] == values[i].valueOf())
-    assertTrue(values[i].valueOf() == values[i])
-    assertFalse(Object(values[i]) === Object(values[i]))
-    assertEquals(Object(values[i]).valueOf(), Object(values[i]).valueOf())
+  assertSame(instance, instance)
+  assertEquals(instance, instance)
+  assertTrue(Object.is(instance, instance))
+  assertTrue(instance === instance)
+  assertTrue(instance == instance)
+  assertFalse(instance === Object(instance))
+  assertFalse(Object(instance) === instance)
+  assertFalse(instance == Object(instance))
+  assertFalse(Object(instance) == instance)
+  assertTrue(instance === instance.valueOf())
+  assertTrue(instance.valueOf() === instance)
+  assertTrue(instance == instance.valueOf())
+  assertTrue(instance.valueOf() == instance)
+  assertFalse(Object(instance) === Object(instance))
+  assertEquals(Object(instance).valueOf(), Object(instance).valueOf())
+
+  function notEqual(other) {
+    assertFalse(instance === other)
+    assertFalse(other === instance)
+    assertFalse(instance == other)
+    assertFalse(other == instance)
   }
 
-  // Test structural equivalence.
-  for (var i = 0; i < values.length; i++) {
-    for (var j = i + 1; j < values.length; j++) {
-      var a = values[i], b = values[j],
-          equivalent = areEquivalent(type, lanes, a, b);
-      assertSame(equivalent, a == b);
-      assertSame(equivalent, a === b);
+  // SIMD values should not be equal to instances of different types.
+  checkTypeMatrix(type, function(other) {
+    assertFalse(instance === other)
+    assertFalse(other === instance)
+    assertFalse(instance == other)
+    assertFalse(other == instance)
+  });
+
+  // Test that f(a, b) is the same as f(SIMD(a), SIMD(b)) for equality and
+  // strict equality, at every lane.
+  function test(a, b) {
+    for (var i = 0; i < lanes; i++) {
+      var aval = simdFn.replaceLane(instance, i, a);
+      var bval = simdFn.replaceLane(instance, i, b);
+      assertSame(a == b, aval == bval);
+      assertSame(a === b, aval === bval);
     }
   }
 
-  // SIMD values should not be equal to any other kind of object.
-  var others = [347, 1.275, NaN, "string", null, undefined, {}, function() {}]
-  for (var i in values) {
-    for (var j in others) {
-      assertFalse(values[i] === others[j])
-      assertFalse(others[j] === values[i])
-      assertFalse(values[i] == others[j])
-      assertFalse(others[j] == values[i])
-    }
+  switch (type) {
+    case 'Float32x4':
+      test(1, 2.5);
+      test(1, 1);
+      test(0, 0);
+      test(-0, +0);
+      test(+0, -0);
+      test(-0, -0);
+      test(0, NaN);
+      test(NaN, NaN);
+      break;
+    case 'Int32x4':
+    case 'Int16x8':
+    case 'Int8x16':
+      test(1, 2);
+      test(1, 1);
+      test(1, -1);
+      break;
+    case 'Bool32x4':
+    case 'Bool16x8':
+    case 'Bool8x16':
+      test(true, false);
+      test(false, true);
+      break;
   }
 }
 
 
 function TestSameValue(type, lanes) {
-  // SIMD value types.
-  // All lanes checked.
-  // TODO(bbudge): use loops to test lanes when replaceLane is defined.
-  assertTrue(sameValueBoth(SIMD.Float32x4(1, 2, 3, 4),
-                           SIMD.Float32x4(1, 2, 3, 4)));
-  assertFalse(sameValueBoth(SIMD.Float32x4(1, 2, 3, 4),
-                            SIMD.Float32x4(NaN, 2, 3, 4)));
-  assertFalse(sameValueBoth(SIMD.Float32x4(1, 2, 3, 4),
-                            SIMD.Float32x4(1, NaN, 3, 4)));
-  assertFalse(sameValueBoth(SIMD.Float32x4(1, 2, 3, 4),
-                            SIMD.Float32x4(1, 2, NaN, 4)));
-  assertFalse(sameValueBoth(SIMD.Float32x4(1, 2, 3, 4),
-                            SIMD.Float32x4(1, 2, 3, NaN)));
-  // Special values.
-  // TODO(bbudge): use loops to test lanes when replaceLane is defined.
-  assertTrue(sameValueBoth(SIMD.Float32x4(NaN, 2, 3, 4),
-                           SIMD.Float32x4(NaN, 2, 3, 4)));
-  assertTrue(sameValueBoth(SIMD.Float32x4(+0, 2, 3, 4),
-                           SIMD.Float32x4(+0, 2, 3, 4)));
-  assertTrue(sameValueBoth(SIMD.Float32x4(-0, 2, 3, 4),
-                           SIMD.Float32x4(-0, 2, 3, 4)));
-  assertTrue(sameValueZeroOnly(SIMD.Float32x4(+0, 2, 3, 4),
-                               SIMD.Float32x4(-0, 2, 3, 4)));
-  assertTrue(sameValueZeroOnly(SIMD.Float32x4(-0, 2, 3, 4),
-                               SIMD.Float32x4(+0, 2, 3, 4)));
+  var simdFn = SIMD[type];
+  var instance = createInstance(type);
+  var sameValue = natives.$sameValue;
+  var sameValueZero = natives.$sameValueZero;
+
+  // SIMD values should not be the same as instances of different types.
+  checkTypeMatrix(type, function(other) {
+    assertFalse(sameValue(instance, other));
+    assertFalse(sameValueZero(instance, other));
+  });
+
+  // Test that f(a, b) is the same as f(SIMD(a), SIMD(b)) for sameValue and
+  // sameValueZero, at every lane.
+  function test(a, b) {
+    for (var i = 0; i < lanes; i++) {
+      var aval = simdFn.replaceLane(instance, i, a);
+      var bval = simdFn.replaceLane(instance, i, b);
+      assertSame(sameValue(a, b), sameValue(aval, bval));
+      assertSame(sameValueZero(a, b), sameValueZero(aval, bval));
+    }
+  }
+
+  switch (type) {
+    case 'Float32x4':
+      test(1, 2.5);
+      test(1, 1);
+      test(0, 0);
+      test(-0, +0);
+      test(+0, -0);
+      test(-0, -0);
+      test(0, NaN);
+      test(NaN, NaN);
+      break;
+    case 'Int32x4':
+    case 'Int16x8':
+    case 'Int8x16':
+      test(1, 2);
+      test(1, 1);
+      test(1, -1);
+      break;
+    case 'Bool32x4':
+    case 'Bool16x8':
+    case 'Bool8x16':
+      test(true, false);
+      test(false, true);
+      break;
+  }
 }
 
 
 function TestComparison(type, lanes) {
-  var a = values[0], b = values[1];
-
-  function lt() { a < b; }
-  function gt() { a > b; }
-  function le() { a <= b; }
-  function ge() { a >= b; }
-  function lt_same() { a < a; }
-  function gt_same() { a > a; }
-  function le_same() { a <= a; }
-  function ge_same() { a >= a; }
-
-  var throwFuncs = [lt, gt, le, ge, lt_same, gt_same, le_same, ge_same];
-
-  for (var f of throwFuncs) {
-    assertThrows(f, TypeError);
-    %OptimizeFunctionOnNextCall(f);
-    assertThrows(f, TypeError);
-    assertThrows(f, TypeError);
+  var simdFn = SIMD[type];
+  var a = createInstance(type), b = createInstance(type);
+
+  function compare(other) {
+    var throwFuncs = [
+      function lt() { a < b; },
+      function gt() { a > b; },
+      function le() { a <= b; },
+      function ge() { a >= b; },
+      function lt_same() { a < a; },
+      function gt_same() { a > a; },
+      function le_same() { a <= a; },
+      function ge_same() { a >= a; },
+    ];
+
+    for (var f of throwFuncs) {
+      assertThrows(f, TypeError);
+      %OptimizeFunctionOnNextCall(f);
+      assertThrows(f, TypeError);
+      assertThrows(f, TypeError);
+    }
   }
+
+  // Test comparison against the same SIMD type.
+  compare(b);
+  // Test comparison against other types.
+  checkTypeMatrix(type, compare);
 }
 
 
 // Test SIMD value wrapping/boxing over non-builtins.
 function TestCall(type, lanes) {
   var simdFn = SIMD[type];
+  var instance = createInstance(type);
   simdFn.prototype.getThisProto = function () {
     return Object.getPrototypeOf(this);
   }
-  for (var i in values) {
-    assertTrue(values[i].getThisProto() === simdFn.prototype)
-  }
+  assertTrue(instance.getThisProto() === simdFn.prototype)
 }
 
 
 function TestAsSetKey(type, lanes, set) {
+  var simdFn = SIMD[type];
+  var instance = createInstance(type);
+
   function test(set, key) {
     assertFalse(set.has(key));
     assertFalse(set.delete(key));
@@ -323,13 +459,14 @@ function TestAsSetKey(type, lanes, set) {
     assertFalse(set.has(key));
   }
 
-  for (var i in values) {
-    test(set, values[i]);
-  }
+  test(set, instance);
 }
 
 
 function TestAsMapKey(type, lanes, map) {
+  var simdFn = SIMD[type];
+  var instance = createInstance(type);
+
   function test(map, key, value) {
     assertFalse(map.has(key));
     assertSame(undefined, map.get(key));
@@ -350,42 +487,40 @@ function TestAsMapKey(type, lanes, map) {
     assertSame(undefined, map.get(key));
   }
 
-  for (var i in values) {
-    test(map, values[i], {});
-  }
+  test(map, instance, {});
 }
 
 
 // Test SIMD type with Harmony reflect-apply.
 function TestReflectApply(type) {
+  var simdFn = SIMD[type];
+  var instance = createInstance(type);
+
   function returnThis() { return this; }
   function returnThisStrict() { 'use strict'; return this; }
   function noop() {}
   function noopStrict() { 'use strict'; }
   var R = void 0;
 
-  for (var i in values) {
-    assertSame(SIMD[type].prototype,
-               Object.getPrototypeOf(
-                  Reflect.apply(returnThis, values[i], [])));
-    assertSame(values[i], Reflect.apply(returnThisStrict, values[i], []));
-
-    assertThrows(
-        function() { 'use strict'; Reflect.apply(values[i]); }, TypeError);
-    assertThrows(
-        function() { Reflect.apply(values[i]); }, TypeError);
-    assertThrows(
-        function() { Reflect.apply(noopStrict, R, values[i]); }, TypeError);
-    assertThrows(
-        function() { Reflect.apply(noop, R, values[i]); }, TypeError);
-  }
+  assertSame(SIMD[type].prototype,
+             Object.getPrototypeOf(
+                Reflect.apply(returnThis, instance, [])));
+  assertSame(instance, Reflect.apply(returnThisStrict, instance, []));
+
+  assertThrows(
+      function() { 'use strict'; Reflect.apply(instance); }, TypeError);
+  assertThrows(
+      function() { Reflect.apply(instance); }, TypeError);
+  assertThrows(
+      function() { Reflect.apply(noopStrict, R, instance); }, TypeError);
+  assertThrows(
+      function() { Reflect.apply(noop, R, instance); }, TypeError);
 }
 
 
 function TestSIMDTypes() {
-  var types = [ 'Float32x4' ];
-  for (var i = 0; i < types.length; ++i) {
-    var type = types[i],
+  for (var i = 0; i < simdTypeNames.length; ++i) {
+    var type = simdTypeNames[i],
         lanes = lanesForType(type);
     TestConstructor(type, lanes);
     TestType(type, lanes);
@@ -395,6 +530,7 @@ function TestSIMDTypes() {
     TestToBoolean(type, lanes);
     TestToString(type, lanes);
     TestToNumber(type, lanes);
+    TestCoercions(type, lanes);
     TestEquality(type, lanes);
     TestSameValue(type, lanes);
     TestComparison(type, lanes);
@@ -407,3 +543,18 @@ function TestSIMDTypes() {
   }
 }
 TestSIMDTypes();
+
+// Tests for the global SIMD object.
+function TestSIMDObject() {
+  assertSame(typeof SIMD, 'object');
+  assertSame(SIMD.constructor, Object);
+  assertSame(Object.getPrototypeOf(SIMD), Object.prototype);
+  assertSame(SIMD + "", "[object SIMD]");
+  // The SIMD object is mutable.
+  SIMD.foo = "foo";
+  assertSame(SIMD.foo, "foo");
+  delete SIMD.foo;
+  delete SIMD.Bool8x16;
+  assertSame(SIMD.Bool8x16, undefined);
+}
+TestSIMDObject()
index 8941e2fdc1cdc66f564ff1b418f2527b5a955a7f..c90d6cc9d181f571307da929197076cd60a89e6d 100644 (file)
@@ -33,6 +33,7 @@ var console = {
   log: function(x) { print(x); },
 };
 
-// Disable value type tests for now, since the polyfill can't pass them.
-// TODO(bbudge): Drop when polyfill is not needed.
+
+// Disable value type tests for now. The value semantics tests are incorrect.
+// TODO(bbudge): Drop when tests are fixed.
 var skipValueTests = true;