Revert of Remove ExternalArray, derived types, and element kinds (patchset #5 id...
authormachenbach <machenbach@chromium.org>
Mon, 27 Jul 2015 20:32:00 +0000 (13:32 -0700)
committerCommit bot <commit-bot@chromium.org>
Mon, 27 Jul 2015 20:32:16 +0000 (20:32 +0000)
Reason for revert:
[Sheriff] Breaks several layout tests, e.g.:
http://build.chromium.org/p/client.v8.fyi/builders/V8-Blink%20Linux%2032/builds/1067

Several output lines change from PASS to FAIL. If the changes are intended, please land a needsmanualrebaseline change in blink first.

Original issue's description:
> Remove ExternalArray, derived types, and element kinds
>
> BUG=v8:3996
> R=jarin@chromium.org, mvstanton@chromium.org, bmeurer@chromium.org
> LOG=y
>
> Committed: https://crrev.com/607ef7c6009a24ebf195b4cab7b0b436c5afd21c
> Cr-Commit-Position: refs/heads/master@{#29872}

TBR=bmeurer@chromium.org,hpayer@chromium.org,jarin@chromium.org,mvstanton@chromium.org,jochen@chromium.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=v8:3996

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

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

62 files changed:
include/v8.h
src/arm/lithium-arm.cc
src/arm/lithium-arm.h
src/arm/lithium-codegen-arm.cc
src/arm64/lithium-arm64.cc
src/arm64/lithium-codegen-arm64.cc
src/bootstrapper.cc
src/code-stubs-hydrogen.cc
src/code-stubs.cc
src/compiler/access-builder.cc
src/compiler/access-builder.h
src/compiler/js-typed-lowering.cc
src/contexts.h
src/elements-kind.cc
src/elements-kind.h
src/elements.cc
src/factory.cc
src/factory.h
src/heap-snapshot-generator.cc
src/heap/heap.cc
src/heap/heap.h
src/heap/objects-visiting.cc
src/hydrogen-instructions.cc
src/hydrogen-instructions.h
src/hydrogen-uint32-analysis.cc
src/hydrogen.cc
src/ia32/lithium-codegen-ia32.cc
src/ia32/lithium-ia32.cc
src/ia32/lithium-ia32.h
src/ic/handler-compiler.cc
src/ic/ic-compiler.cc
src/ic/ic.cc
src/lookup.cc
src/mips/lithium-codegen-mips.cc
src/mips/lithium-mips.cc
src/mips/lithium-mips.h
src/mips64/lithium-codegen-mips64.cc
src/mips64/lithium-mips64.cc
src/mips64/lithium-mips64.h
src/objects-debug.cc
src/objects-inl.h
src/objects-printer.cc
src/objects.cc
src/objects.h
src/ppc/lithium-codegen-ppc.cc
src/ppc/lithium-ppc.cc
src/ppc/lithium-ppc.h
src/runtime/runtime-array.cc
src/runtime/runtime-test.cc
src/runtime/runtime-typedarray.cc
src/runtime/runtime.h
src/x64/lithium-codegen-x64.cc
src/x64/lithium-x64.cc
src/x64/lithium-x64.h
src/x87/lithium-codegen-x87.cc
src/x87/lithium-x87.cc
src/x87/lithium-x87.h
test/cctest/compiler/test-run-properties.cc
test/cctest/test-api.cc
test/mjsunit/elements-kind.js
test/mjsunit/opt-elements-kind.js
test/mjsunit/osr-elements-kind.js

index 50f0f5fd274138f25472e0c3c45ca739c06d04e1..084d41a71b79b6e5fc3aef239fc96e3e8c5eb80d 100644 (file)
@@ -6946,7 +6946,7 @@ class Internals {
   static const int kNodeIsIndependentShift = 3;
   static const int kNodeIsPartiallyDependentShift = 4;
 
-  static const int kJSObjectType = 0xb6;
+  static const int kJSObjectType = 0xbf;
   static const int kFirstNonstringType = 0x80;
   static const int kOddballType = 0x83;
   static const int kForeignType = 0x87;
index 49747b7751889eb60e72e38572c95da567bcf358..ad34013a2a92391aea36c4e2a1fd694bc3de698e 100644 (file)
@@ -2240,7 +2240,7 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
   LOperand* key = UseRegisterOrConstantAtStart(instr->key());
   LInstruction* result = NULL;
 
-  if (!instr->is_fixed_typed_array()) {
+  if (!instr->is_typed_elements()) {
     LOperand* obj = NULL;
     if (instr->representation().IsDouble()) {
       obj = UseRegister(instr->elements());
@@ -2260,9 +2260,10 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
   }
 
   bool needs_environment;
-  if (instr->is_fixed_typed_array()) {
+  if (instr->is_external() || instr->is_fixed_typed_array()) {
     // see LCodeGen::DoLoadKeyedExternalArray
-    needs_environment = elements_kind == UINT32_ELEMENTS &&
+    needs_environment = (elements_kind == EXTERNAL_UINT32_ELEMENTS ||
+                         elements_kind == UINT32_ELEMENTS) &&
                         !instr->CheckFlag(HInstruction::kUint32);
   } else {
     // see LCodeGen::DoLoadKeyedFixedDoubleArray and
@@ -2297,7 +2298,7 @@ LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
 
 
 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
-  if (!instr->is_fixed_typed_array()) {
+  if (!instr->is_typed_elements()) {
     DCHECK(instr->elements()->representation().IsTagged());
     bool needs_write_barrier = instr->NeedsWriteBarrier();
     LOperand* object = NULL;
index 7f2ab11b2dd4f71ace90797a863714012f88f296..4eeca332ec1e834d77188855f9d4862c09b9d884 100644 (file)
@@ -1647,9 +1647,15 @@ class LLoadKeyed final : public LTemplateInstruction<1, 2, 0> {
   ElementsKind elements_kind() const {
     return hydrogen()->elements_kind();
   }
+  bool is_external() const {
+    return hydrogen()->is_external();
+  }
   bool is_fixed_typed_array() const {
     return hydrogen()->is_fixed_typed_array();
   }
+  bool is_typed_elements() const {
+    return is_external() || is_fixed_typed_array();
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
   DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
@@ -2249,9 +2255,13 @@ class LStoreKeyed final : public LTemplateInstruction<0, 3, 0> {
     inputs_[2] = value;
   }
 
+  bool is_external() const { return hydrogen()->is_external(); }
   bool is_fixed_typed_array() const {
     return hydrogen()->is_fixed_typed_array();
   }
+  bool is_typed_elements() const {
+    return is_external() || is_fixed_typed_array();
+  }
   LOperand* elements() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
   LOperand* value() { return inputs_[2]; }
index 5fe81d25538ee2ec13ceb15d6342cd3c4083943d..97881ba1a2d3c7dca6b9c4b15cc456dbecbf414a 100644 (file)
@@ -3190,13 +3190,17 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
       ? (element_size_shift - kSmiTagSize) : element_size_shift;
   int base_offset = instr->base_offset();
 
-  if (elements_kind == FLOAT32_ELEMENTS || elements_kind == FLOAT64_ELEMENTS) {
+  if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+      elements_kind == FLOAT32_ELEMENTS ||
+      elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
+      elements_kind == FLOAT64_ELEMENTS) {
     DwVfpRegister result = ToDoubleRegister(instr->result());
     Operand operand = key_is_constant
         ? Operand(constant_key << element_size_shift)
         : Operand(key, LSL, shift_size);
     __ add(scratch0(), external_pointer, operand);
-    if (elements_kind == FLOAT32_ELEMENTS) {
+    if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+        elements_kind == FLOAT32_ELEMENTS) {
       __ vldr(double_scratch0().low(), scratch0(), base_offset);
       __ vcvt_f64_f32(result, double_scratch0().low());
     } else  {  // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
@@ -3208,22 +3212,29 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
         key, external_pointer, key_is_constant, constant_key,
         element_size_shift, shift_size, base_offset);
     switch (elements_kind) {
+      case EXTERNAL_INT8_ELEMENTS:
       case INT8_ELEMENTS:
         __ ldrsb(result, mem_operand);
         break;
+      case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
+      case EXTERNAL_UINT8_ELEMENTS:
       case UINT8_ELEMENTS:
       case UINT8_CLAMPED_ELEMENTS:
         __ ldrb(result, mem_operand);
         break;
+      case EXTERNAL_INT16_ELEMENTS:
       case INT16_ELEMENTS:
         __ ldrsh(result, mem_operand);
         break;
+      case EXTERNAL_UINT16_ELEMENTS:
       case UINT16_ELEMENTS:
         __ ldrh(result, mem_operand);
         break;
+      case EXTERNAL_INT32_ELEMENTS:
       case INT32_ELEMENTS:
         __ ldr(result, mem_operand);
         break;
+      case EXTERNAL_UINT32_ELEMENTS:
       case UINT32_ELEMENTS:
         __ ldr(result, mem_operand);
         if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
@@ -3233,6 +3244,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
         break;
       case FLOAT32_ELEMENTS:
       case FLOAT64_ELEMENTS:
+      case EXTERNAL_FLOAT32_ELEMENTS:
+      case EXTERNAL_FLOAT64_ELEMENTS:
       case FAST_HOLEY_DOUBLE_ELEMENTS:
       case FAST_HOLEY_ELEMENTS:
       case FAST_HOLEY_SMI_ELEMENTS:
@@ -3342,7 +3355,7 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
 
 
 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
-  if (instr->is_fixed_typed_array()) {
+  if (instr->is_typed_elements()) {
     DoLoadKeyedExternalArray(instr);
   } else if (instr->hydrogen()->representation().IsDouble()) {
     DoLoadKeyedFixedDoubleArray(instr);
@@ -4304,7 +4317,10 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
       ? (element_size_shift - kSmiTagSize) : element_size_shift;
   int base_offset = instr->base_offset();
 
-  if (elements_kind == FLOAT32_ELEMENTS || elements_kind == FLOAT64_ELEMENTS) {
+  if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+      elements_kind == FLOAT32_ELEMENTS ||
+      elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
+      elements_kind == FLOAT64_ELEMENTS) {
     Register address = scratch0();
     DwVfpRegister value(ToDoubleRegister(instr->value()));
     if (key_is_constant) {
@@ -4317,7 +4333,8 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
     } else {
       __ add(address, external_pointer, Operand(key, LSL, shift_size));
     }
-    if (elements_kind == FLOAT32_ELEMENTS) {
+    if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+        elements_kind == FLOAT32_ELEMENTS) {
       __ vcvt_f32_f64(double_scratch0().low(), value);
       __ vstr(double_scratch0().low(), address, base_offset);
     } else {  // Storing doubles, not floats.
@@ -4330,21 +4347,30 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
         element_size_shift, shift_size,
         base_offset);
     switch (elements_kind) {
+      case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
+      case EXTERNAL_INT8_ELEMENTS:
+      case EXTERNAL_UINT8_ELEMENTS:
       case UINT8_ELEMENTS:
       case UINT8_CLAMPED_ELEMENTS:
       case INT8_ELEMENTS:
         __ strb(value, mem_operand);
         break;
+      case EXTERNAL_INT16_ELEMENTS:
+      case EXTERNAL_UINT16_ELEMENTS:
       case INT16_ELEMENTS:
       case UINT16_ELEMENTS:
         __ strh(value, mem_operand);
         break;
+      case EXTERNAL_INT32_ELEMENTS:
+      case EXTERNAL_UINT32_ELEMENTS:
       case INT32_ELEMENTS:
       case UINT32_ELEMENTS:
         __ str(value, mem_operand);
         break;
       case FLOAT32_ELEMENTS:
       case FLOAT64_ELEMENTS:
+      case EXTERNAL_FLOAT32_ELEMENTS:
+      case EXTERNAL_FLOAT64_ELEMENTS:
       case FAST_DOUBLE_ELEMENTS:
       case FAST_ELEMENTS:
       case FAST_SMI_ELEMENTS:
@@ -4450,7 +4476,7 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
 
 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
   // By cases: external, fast double
-  if (instr->is_fixed_typed_array()) {
+  if (instr->is_typed_elements()) {
     DoStoreKeyedExternalArray(instr);
   } else if (instr->hydrogen()->value()->representation().IsDouble()) {
     DoStoreKeyedFixedDoubleArray(instr);
index 2c12ce0f1387f2c75a5e7081d48b9d5ff12dc3b3..e1119c2c678e4941ebb47e344ab5979dd9939a3c 100644 (file)
@@ -1731,7 +1731,7 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
   LOperand* elements = UseRegister(instr->elements());
   LOperand* key = UseRegisterOrConstant(instr->key());
 
-  if (!instr->is_fixed_typed_array()) {
+  if (!instr->is_typed_elements()) {
     if (instr->representation().IsDouble()) {
       LOperand* temp = (!instr->key()->IsConstant() ||
                         instr->RequiresHoleCheck())
@@ -1765,7 +1765,8 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
     LOperand* temp = instr->key()->IsConstant() ? NULL : TempRegister();
     LInstruction* result = DefineAsRegister(
         new(zone()) LLoadKeyedExternal(elements, key, temp));
-    if (elements_kind == UINT32_ELEMENTS &&
+    if ((elements_kind == EXTERNAL_UINT32_ELEMENTS ||
+         elements_kind == UINT32_ELEMENTS) &&
         !instr->CheckFlag(HInstruction::kUint32)) {
       result = AssignEnvironment(result);
     }
@@ -2369,7 +2370,7 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
   LOperand* elements = NULL;
   LOperand* val = NULL;
 
-  if (!instr->is_fixed_typed_array() &&
+  if (!instr->is_typed_elements() &&
       instr->value()->representation().IsTagged() &&
       instr->NeedsWriteBarrier()) {
     // RecordWrite() will clobber all registers.
@@ -2382,7 +2383,7 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
     temp = instr->key()->IsConstant() ? NULL : TempRegister();
   }
 
-  if (instr->is_fixed_typed_array()) {
+  if (instr->is_typed_elements()) {
     DCHECK((instr->value()->representation().IsInteger32() &&
             !IsDoubleOrFloatElementsKind(instr->elements_kind())) ||
            (instr->value()->representation().IsDouble() &&
index 5502e7beaf7d2a27a448069e05a074bc9fa96edf..cac7f92ec78beb37a57c128d17082dc721dc5f35 100644 (file)
@@ -3458,33 +3458,42 @@ void LCodeGen::DoLoadKeyedExternal(LLoadKeyedExternal* instr) {
                                        elements_kind,
                                        instr->base_offset());
 
-  if (elements_kind == FLOAT32_ELEMENTS) {
+  if ((elements_kind == EXTERNAL_FLOAT32_ELEMENTS) ||
+      (elements_kind == FLOAT32_ELEMENTS)) {
     DoubleRegister result = ToDoubleRegister(instr->result());
     __ Ldr(result.S(), mem_op);
     __ Fcvt(result, result.S());
-  } else if (elements_kind == FLOAT64_ELEMENTS) {
+  } else if ((elements_kind == EXTERNAL_FLOAT64_ELEMENTS) ||
+             (elements_kind == FLOAT64_ELEMENTS)) {
     DoubleRegister result = ToDoubleRegister(instr->result());
     __ Ldr(result, mem_op);
   } else {
     Register result = ToRegister(instr->result());
 
     switch (elements_kind) {
+      case EXTERNAL_INT8_ELEMENTS:
       case INT8_ELEMENTS:
         __ Ldrsb(result, mem_op);
         break;
+      case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
+      case EXTERNAL_UINT8_ELEMENTS:
       case UINT8_ELEMENTS:
       case UINT8_CLAMPED_ELEMENTS:
         __ Ldrb(result, mem_op);
         break;
+      case EXTERNAL_INT16_ELEMENTS:
       case INT16_ELEMENTS:
         __ Ldrsh(result, mem_op);
         break;
+      case EXTERNAL_UINT16_ELEMENTS:
       case UINT16_ELEMENTS:
         __ Ldrh(result, mem_op);
         break;
+      case EXTERNAL_INT32_ELEMENTS:
       case INT32_ELEMENTS:
         __ Ldrsw(result, mem_op);
         break;
+      case EXTERNAL_UINT32_ELEMENTS:
       case UINT32_ELEMENTS:
         __ Ldr(result.W(), mem_op);
         if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
@@ -3495,6 +3504,8 @@ void LCodeGen::DoLoadKeyedExternal(LLoadKeyedExternal* instr) {
         break;
       case FLOAT32_ELEMENTS:
       case FLOAT64_ELEMENTS:
+      case EXTERNAL_FLOAT32_ELEMENTS:
+      case EXTERNAL_FLOAT64_ELEMENTS:
       case FAST_HOLEY_DOUBLE_ELEMENTS:
       case FAST_HOLEY_ELEMENTS:
       case FAST_HOLEY_SMI_ELEMENTS:
@@ -5169,33 +5180,44 @@ void LCodeGen::DoStoreKeyedExternal(LStoreKeyedExternal* instr) {
                                      elements_kind,
                                      instr->base_offset());
 
-  if (elements_kind == FLOAT32_ELEMENTS) {
+  if ((elements_kind == EXTERNAL_FLOAT32_ELEMENTS) ||
+      (elements_kind == FLOAT32_ELEMENTS)) {
     DoubleRegister value = ToDoubleRegister(instr->value());
     DoubleRegister dbl_scratch = double_scratch();
     __ Fcvt(dbl_scratch.S(), value);
     __ Str(dbl_scratch.S(), dst);
-  } else if (elements_kind == FLOAT64_ELEMENTS) {
+  } else if ((elements_kind == EXTERNAL_FLOAT64_ELEMENTS) ||
+             (elements_kind == FLOAT64_ELEMENTS)) {
     DoubleRegister value = ToDoubleRegister(instr->value());
     __ Str(value, dst);
   } else {
     Register value = ToRegister(instr->value());
 
     switch (elements_kind) {
+      case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
+      case EXTERNAL_INT8_ELEMENTS:
+      case EXTERNAL_UINT8_ELEMENTS:
       case UINT8_ELEMENTS:
       case UINT8_CLAMPED_ELEMENTS:
       case INT8_ELEMENTS:
         __ Strb(value, dst);
         break;
+      case EXTERNAL_INT16_ELEMENTS:
+      case EXTERNAL_UINT16_ELEMENTS:
       case INT16_ELEMENTS:
       case UINT16_ELEMENTS:
         __ Strh(value, dst);
         break;
+      case EXTERNAL_INT32_ELEMENTS:
+      case EXTERNAL_UINT32_ELEMENTS:
       case INT32_ELEMENTS:
       case UINT32_ELEMENTS:
         __ Str(value.W(), dst);
         break;
       case FLOAT32_ELEMENTS:
       case FLOAT64_ELEMENTS:
+      case EXTERNAL_FLOAT32_ELEMENTS:
+      case EXTERNAL_FLOAT64_ELEMENTS:
       case FAST_DOUBLE_ELEMENTS:
       case FAST_ELEMENTS:
       case FAST_SMI_ELEMENTS:
index 561f7e094458258a8ab7001cd0b0da6e3c510c8d..71b61e6b52c573e4f64ea64926dee37a9d4c3b0b 100644 (file)
@@ -235,8 +235,11 @@ class Genesis BASE_EMBEDDED {
                                           ElementsKind elements_kind);
   bool InstallNatives(ContextType context_type);
 
-  void InstallTypedArray(const char* name, ElementsKind elements_kind,
-                         Handle<JSFunction>* fun);
+  void InstallTypedArray(
+      const char* name,
+      ElementsKind elements_kind,
+      Handle<JSFunction>* fun,
+      Handle<Map>* external_map);
   bool InstallExperimentalNatives();
   bool InstallExtraNatives();
   void InstallBuiltinFunctionIds();
@@ -1281,12 +1284,17 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> global_object,
   }
 
   {  // -- T y p e d A r r a y s
-#define INSTALL_TYPED_ARRAY(Type, type, TYPE, ctype, size)   \
-  {                                                          \
-    Handle<JSFunction> fun;                                  \
-    InstallTypedArray(#Type "Array", TYPE##_ELEMENTS, &fun); \
-    native_context()->set_##type##_array_fun(*fun);          \
-  }
+#define INSTALL_TYPED_ARRAY(Type, type, TYPE, ctype, size)                    \
+    {                                                                         \
+      Handle<JSFunction> fun;                                                 \
+      Handle<Map> external_map;                                               \
+      InstallTypedArray(#Type "Array",                                        \
+          TYPE##_ELEMENTS,                                                    \
+          &fun,                                                               \
+          &external_map);                                                     \
+      native_context()->set_##type##_array_fun(*fun);                         \
+      native_context()->set_##type##_array_external_map(*external_map);       \
+    }
     TYPED_ARRAYS(INSTALL_TYPED_ARRAY)
 #undef INSTALL_TYPED_ARRAY
 
@@ -1497,8 +1505,11 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> global_object,
 }
 
 
-void Genesis::InstallTypedArray(const char* name, ElementsKind elements_kind,
-                                Handle<JSFunction>* fun) {
+void Genesis::InstallTypedArray(
+    const char* name,
+    ElementsKind elements_kind,
+    Handle<JSFunction>* fun,
+    Handle<Map>* external_map) {
   Handle<JSObject> global = Handle<JSObject>(native_context()->global_object());
   Handle<JSFunction> result = InstallFunction(
       global, name, JS_TYPED_ARRAY_TYPE, JSTypedArray::kSize,
@@ -1511,6 +1522,9 @@ void Genesis::InstallTypedArray(const char* name, ElementsKind elements_kind,
   JSFunction::SetInitialMap(result, initial_map,
                             handle(initial_map->prototype(), isolate()));
   *fun = result;
+
+  ElementsKind external_kind = GetNextTransitionElementsKind(elements_kind);
+  *external_map = Map::AsElementsKind(initial_map, external_kind);
 }
 
 
index fb46633f0b3c961f20931053ea2a26d24263e885..d5addc0368d864828f6ca4c0db0390566b40e1db 100644 (file)
@@ -1987,6 +1987,13 @@ class CodeStubGraphBuilder<KeyedLoadGenericStub>
                             HValue* bit_field2,
                             ElementsKind kind);
 
+  void BuildExternalElementLoad(HGraphBuilder::IfBuilder* if_builder,
+                                HValue* receiver,
+                                HValue* key,
+                                HValue* instance_type,
+                                HValue* bit_field2,
+                                ElementsKind kind);
+
   KeyedLoadGenericStub* casted_stub() {
     return static_cast<KeyedLoadGenericStub*>(stub());
   }
@@ -2008,6 +2015,8 @@ void CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildElementsKindLimitCheck(
 void CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildFastElementLoad(
     HGraphBuilder::IfBuilder* if_builder, HValue* receiver, HValue* key,
     HValue* instance_type, HValue* bit_field2, ElementsKind kind) {
+  DCHECK(!IsExternalArrayElementsKind(kind));
+
   BuildElementsKindLimitCheck(if_builder, bit_field2, kind);
 
   IfBuilder js_array_check(this);
@@ -2027,6 +2036,20 @@ void CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildFastElementLoad(
 }
 
 
+void CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildExternalElementLoad(
+    HGraphBuilder::IfBuilder* if_builder, HValue* receiver, HValue* key,
+    HValue* instance_type, HValue* bit_field2, ElementsKind kind) {
+  DCHECK(IsExternalArrayElementsKind(kind));
+
+  BuildElementsKindLimitCheck(if_builder, bit_field2, kind);
+
+  Push(BuildUncheckedMonomorphicElementAccess(receiver, key, NULL,
+                                              false, kind,
+                                              LOAD, NEVER_RETURN_HOLE,
+                                              STANDARD_STORE));
+}
+
+
 HValue* CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildCodeStub() {
   HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex);
   HValue* key = GetParameter(LoadDescriptor::kNameIndex);
@@ -2088,6 +2111,42 @@ HValue* CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildCodeStub() {
                      Deoptimizer::EAGER);
     Push(graph()->GetConstant0());
 
+    kind_if.Else();
+    BuildExternalElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
+                             EXTERNAL_INT8_ELEMENTS);
+
+    kind_if.Else();
+    BuildExternalElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
+                             EXTERNAL_UINT8_ELEMENTS);
+
+    kind_if.Else();
+    BuildExternalElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
+                             EXTERNAL_INT16_ELEMENTS);
+
+    kind_if.Else();
+    BuildExternalElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
+                             EXTERNAL_UINT16_ELEMENTS);
+
+    kind_if.Else();
+    BuildExternalElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
+                             EXTERNAL_INT32_ELEMENTS);
+
+    kind_if.Else();
+    BuildExternalElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
+                             EXTERNAL_UINT32_ELEMENTS);
+
+    kind_if.Else();
+    BuildExternalElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
+                             EXTERNAL_FLOAT32_ELEMENTS);
+
+    kind_if.Else();
+    BuildExternalElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
+                             EXTERNAL_FLOAT64_ELEMENTS);
+
+    kind_if.Else();
+    BuildExternalElementLoad(&kind_if, receiver, key, instance_type, bit_field2,
+                             EXTERNAL_UINT8_CLAMPED_ELEMENTS);
+
     kind_if.ElseDeopt(
         Deoptimizer::kElementsKindUnhandledInKeyedLoadGenericStub);
 
@@ -2175,7 +2234,7 @@ HValue* CodeStubGraphBuilder<KeyedLoadGenericStub>::BuildCodeStub() {
             index->ClearFlag(HValue::kCanOverflow);
             HValue* property_index =
                 Add<HLoadKeyed>(cache_field_offsets, index, nullptr,
-                                INT32_ELEMENTS, NEVER_RETURN_HOLE, 0);
+                                EXTERNAL_INT32_ELEMENTS, NEVER_RETURN_HOLE, 0);
             Push(property_index);
           }
           lookup_if->Else();
index ee57db741e3714ef45c5fb913c17b1f5a2461126..877da682f2ce2589800d2a00e41594d6dd17d843 100644 (file)
@@ -807,6 +807,7 @@ void StoreElementStub::Generate(MacroAssembler* masm) {
     case FAST_DOUBLE_ELEMENTS:
     case FAST_HOLEY_DOUBLE_ELEMENTS:
 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
+    case EXTERNAL_##TYPE##_ELEMENTS:                    \
     case TYPE##_ELEMENTS:
 
     TYPED_ARRAYS(TYPED_ARRAY_CASE)
index b54982f4c9288e06e6da4af72a97e050d1444851..24701634748a363747cff0d0cc715f386bd723fe 100644 (file)
@@ -80,6 +80,14 @@ FieldAccess AccessBuilder::ForFixedArrayLength() {
 }
 
 
+// static
+FieldAccess AccessBuilder::ForExternalArrayPointer() {
+  FieldAccess access = {kTaggedBase, ExternalArray::kExternalPointerOffset,
+                        MaybeHandle<Name>(), Type::UntaggedPointer(), kMachPtr};
+  return access;
+}
+
+
 // static
 FieldAccess AccessBuilder::ForDescriptorArrayEnumCache() {
   FieldAccess access = {kTaggedBase, DescriptorArray::kEnumCacheOffset,
index 95be3e0dd84b7ad9c9ac97b566f402359b1899be..240ffdcb5dac59d11998b0bf7cf0c0b386f61197 100644 (file)
@@ -43,6 +43,9 @@ class AccessBuilder final : public AllStatic {
   // Provides access to FixedArray::length() field.
   static FieldAccess ForFixedArrayLength();
 
+  // Provides access to ExternalArray::external_pointer() field.
+  static FieldAccess ForExternalArrayPointer();
+
   // Provides access to DescriptorArray::enum_cache() field.
   static FieldAccess ForDescriptorArrayEnumCache();
 
index 628e7e07b69b1ae2ec4560e6c41058d2abdd58c5..ea1b4644f2a3fa4bb4c57304601347cfc0509318 100644 (file)
@@ -832,10 +832,11 @@ Reduction JSTypedLowering::ReduceJSLoadProperty(Node* node) {
       size_t const k = ElementSizeLog2Of(access.machine_type());
       double const byte_length = array->byte_length()->Number();
       CHECK_LT(k, arraysize(shifted_int32_ranges_));
-      if (key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) {
+      if (IsExternalArrayElementsKind(array->map()->elements_kind()) &&
+          key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) {
         // JSLoadProperty(typed-array, int32)
-        Handle<FixedTypedArrayBase> elements =
-            Handle<FixedTypedArrayBase>::cast(handle(array->elements()));
+        Handle<ExternalArray> elements =
+            Handle<ExternalArray>::cast(handle(array->elements()));
         Node* buffer = jsgraph()->PointerConstant(elements->external_pointer());
         Node* length = jsgraph()->Constant(byte_length);
         Node* effect = NodeProperties::GetEffectInput(node);
@@ -878,11 +879,12 @@ Reduction JSTypedLowering::ReduceJSStoreProperty(Node* node) {
       size_t const k = ElementSizeLog2Of(access.machine_type());
       double const byte_length = array->byte_length()->Number();
       CHECK_LT(k, arraysize(shifted_int32_ranges_));
-      if (access.external_array_type() != kExternalUint8ClampedArray &&
+      if (IsExternalArrayElementsKind(array->map()->elements_kind()) &&
+          access.external_array_type() != kExternalUint8ClampedArray &&
           key_type->Is(shifted_int32_ranges_[k]) && byte_length <= kMaxInt) {
         // JSLoadProperty(typed-array, int32)
-        Handle<FixedTypedArrayBase> elements =
-            Handle<FixedTypedArrayBase>::cast(handle(array->elements()));
+        Handle<ExternalArray> elements =
+            Handle<ExternalArray>::cast(handle(array->elements()));
         Node* buffer = jsgraph()->PointerConstant(elements->external_pointer());
         Node* length = jsgraph()->Constant(byte_length);
         Node* context = NodeProperties::GetContextInput(node);
index 37fc31565c1937a172f2cd174ea50e694e9a7172..fc29831942645a8cce99de3472e4908b178df8d2 100644 (file)
@@ -115,6 +115,16 @@ enum BindingFlags {
   V(FLOAT32_ARRAY_FUN_INDEX, JSFunction, float32_array_fun)                    \
   V(FLOAT64_ARRAY_FUN_INDEX, JSFunction, float64_array_fun)                    \
   V(UINT8_CLAMPED_ARRAY_FUN_INDEX, JSFunction, uint8_clamped_array_fun)        \
+  V(INT8_ARRAY_EXTERNAL_MAP_INDEX, Map, int8_array_external_map)               \
+  V(UINT8_ARRAY_EXTERNAL_MAP_INDEX, Map, uint8_array_external_map)             \
+  V(INT16_ARRAY_EXTERNAL_MAP_INDEX, Map, int16_array_external_map)             \
+  V(UINT16_ARRAY_EXTERNAL_MAP_INDEX, Map, uint16_array_external_map)           \
+  V(INT32_ARRAY_EXTERNAL_MAP_INDEX, Map, int32_array_external_map)             \
+  V(UINT32_ARRAY_EXTERNAL_MAP_INDEX, Map, uint32_array_external_map)           \
+  V(FLOAT32_ARRAY_EXTERNAL_MAP_INDEX, Map, float32_array_external_map)         \
+  V(FLOAT64_ARRAY_EXTERNAL_MAP_INDEX, Map, float64_array_external_map)         \
+  V(UINT8_CLAMPED_ARRAY_EXTERNAL_MAP_INDEX, Map,                               \
+    uint8_clamped_array_external_map)                                          \
   V(DATA_VIEW_FUN_INDEX, JSFunction, data_view_fun)                            \
   V(SLOPPY_FUNCTION_MAP_INDEX, Map, sloppy_function_map)                       \
   V(SLOPPY_FUNCTION_WITH_READONLY_PROTOTYPE_MAP_INDEX, Map,                    \
index 0d29c3047238cbcfe6b0df71b196441686fa3e48..07d2837bdc86ca747d1e4468887f6bfa6b049dfd 100644 (file)
@@ -15,17 +15,26 @@ namespace internal {
 
 int ElementsKindToShiftSize(ElementsKind elements_kind) {
   switch (elements_kind) {
+    case EXTERNAL_INT8_ELEMENTS:
+    case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
+    case EXTERNAL_UINT8_ELEMENTS:
     case UINT8_ELEMENTS:
     case INT8_ELEMENTS:
     case UINT8_CLAMPED_ELEMENTS:
       return 0;
+    case EXTERNAL_INT16_ELEMENTS:
+    case EXTERNAL_UINT16_ELEMENTS:
     case UINT16_ELEMENTS:
     case INT16_ELEMENTS:
       return 1;
+    case EXTERNAL_INT32_ELEMENTS:
+    case EXTERNAL_UINT32_ELEMENTS:
+    case EXTERNAL_FLOAT32_ELEMENTS:
     case UINT32_ELEMENTS:
     case INT32_ELEMENTS:
     case FLOAT32_ELEMENTS:
       return 2;
+    case EXTERNAL_FLOAT64_ELEMENTS:
     case FAST_DOUBLE_ELEMENTS:
     case FAST_HOLEY_DOUBLE_ELEMENTS:
     case FLOAT64_ELEMENTS:
@@ -44,10 +53,16 @@ int ElementsKindToShiftSize(ElementsKind elements_kind) {
 }
 
 
+static bool IsTypedArrayElementsKind(ElementsKind elements_kind) {
+  return IsFixedTypedArrayElementsKind(elements_kind) ||
+         IsExternalArrayElementsKind(elements_kind);
+}
+
+
 int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind) {
   STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize);
 
-  if (IsFixedTypedArrayElementsKind(elements_kind)) {
+  if (IsTypedArrayElementsKind(elements_kind)) {
     return 0;
   } else {
     return FixedArray::kHeaderSize - kHeapObjectTag;
@@ -110,8 +125,17 @@ int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind) {
 
 
 ElementsKind GetNextTransitionElementsKind(ElementsKind kind) {
-  int index = GetSequenceIndexFromFastElementsKind(kind);
-  return GetFastElementsKindFromSequenceIndex(index + 1);
+  switch (kind) {
+#define FIXED_TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
+    case TYPE##_ELEMENTS: return EXTERNAL_##TYPE##_ELEMENTS;
+
+    TYPED_ARRAYS(FIXED_TYPED_ARRAY_CASE)
+#undef FIXED_TYPED_ARRAY_CASE
+    default: {
+      int index = GetSequenceIndexFromFastElementsKind(kind);
+      return GetFastElementsKindFromSequenceIndex(index + 1);
+    }
+  }
 }
 
 
@@ -122,9 +146,18 @@ static inline bool IsFastTransitionTarget(ElementsKind elements_kind) {
 
 bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
                                          ElementsKind to_kind) {
-  if (IsFixedTypedArrayElementsKind(from_kind) ||
-      IsFixedTypedArrayElementsKind(to_kind)) {
-    return false;
+  if (IsTypedArrayElementsKind(from_kind) ||
+      IsTypedArrayElementsKind(to_kind)) {
+    switch (from_kind) {
+#define FIXED_TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
+      case TYPE##_ELEMENTS:                                   \
+        return to_kind == EXTERNAL_##TYPE##_ELEMENTS;
+
+      TYPED_ARRAYS(FIXED_TYPED_ARRAY_CASE);
+#undef FIXED_TYPED_ARRAY_CASE
+      default:
+        return false;
+    }
   }
   if (IsFastElementsKind(from_kind) && IsFastTransitionTarget(to_kind)) {
     switch (from_kind) {
index 0254a4fb59b20e44096138e54458840ba5253d26..c3184b93835313d30efc4f12051ceec49b47053e 100644 (file)
@@ -33,6 +33,17 @@ enum ElementsKind {
   FAST_SLOPPY_ARGUMENTS_ELEMENTS,
   SLOW_SLOPPY_ARGUMENTS_ELEMENTS,
 
+  // The "fast" kind for external arrays
+  EXTERNAL_INT8_ELEMENTS,
+  EXTERNAL_UINT8_ELEMENTS,
+  EXTERNAL_INT16_ELEMENTS,
+  EXTERNAL_UINT16_ELEMENTS,
+  EXTERNAL_INT32_ELEMENTS,
+  EXTERNAL_UINT32_ELEMENTS,
+  EXTERNAL_FLOAT32_ELEMENTS,
+  EXTERNAL_FLOAT64_ELEMENTS,
+  EXTERNAL_UINT8_CLAMPED_ELEMENTS,
+
   // Fixed typed arrays
   UINT8_ELEMENTS,
   INT8_ELEMENTS,
@@ -49,6 +60,8 @@ enum ElementsKind {
   LAST_ELEMENTS_KIND = UINT8_CLAMPED_ELEMENTS,
   FIRST_FAST_ELEMENTS_KIND = FAST_SMI_ELEMENTS,
   LAST_FAST_ELEMENTS_KIND = FAST_HOLEY_DOUBLE_ELEMENTS,
+  FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND = EXTERNAL_INT8_ELEMENTS,
+  LAST_EXTERNAL_ARRAY_ELEMENTS_KIND = EXTERNAL_UINT8_CLAMPED_ELEMENTS,
   FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND = UINT8_ELEMENTS,
   LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND = UINT8_CLAMPED_ELEMENTS,
   TERMINAL_FAST_ELEMENTS_KIND = FAST_HOLEY_ELEMENTS
@@ -84,15 +97,21 @@ inline bool IsSloppyArgumentsElements(ElementsKind kind) {
 }
 
 
-inline bool IsFixedTypedArrayElementsKind(ElementsKind kind) {
-  return kind >= FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND &&
-         kind <= LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND;
+inline bool IsExternalArrayElementsKind(ElementsKind kind) {
+  return kind >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND &&
+      kind <= LAST_EXTERNAL_ARRAY_ELEMENTS_KIND;
 }
 
 
 inline bool IsTerminalElementsKind(ElementsKind kind) {
   return kind == TERMINAL_FAST_ELEMENTS_KIND ||
-         IsFixedTypedArrayElementsKind(kind);
+      IsExternalArrayElementsKind(kind);
+}
+
+
+inline bool IsFixedTypedArrayElementsKind(ElementsKind kind) {
+  return kind >= FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND &&
+      kind <= LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND;
 }
 
 
@@ -114,13 +133,21 @@ inline bool IsFastDoubleElementsKind(ElementsKind kind) {
 }
 
 
+inline bool IsExternalFloatOrDoubleElementsKind(ElementsKind kind) {
+  return kind == EXTERNAL_FLOAT64_ELEMENTS ||
+      kind == EXTERNAL_FLOAT32_ELEMENTS;
+}
+
+
 inline bool IsFixedFloatElementsKind(ElementsKind kind) {
   return kind == FLOAT32_ELEMENTS || kind == FLOAT64_ELEMENTS;
 }
 
 
 inline bool IsDoubleOrFloatElementsKind(ElementsKind kind) {
-  return IsFastDoubleElementsKind(kind) || IsFixedFloatElementsKind(kind);
+  return IsFastDoubleElementsKind(kind) ||
+      IsExternalFloatOrDoubleElementsKind(kind) ||
+      IsFixedFloatElementsKind(kind);
 }
 
 
index 7ef13b30dedc38511410ef9a5bfb91cdd0297f4b..d1ddc8dc481a6778c878e05229344bef86bd22b5 100644 (file)
 //       - FastPackedDoubleElementsAccessor
 //       - FastHoleyDoubleElementsAccessor
 //   - TypedElementsAccessor: template, with instantiations:
+//     - ExternalInt8ElementsAccessor
+//     - ExternalUint8ElementsAccessor
+//     - ExternalInt16ElementsAccessor
+//     - ExternalUint16ElementsAccessor
+//     - ExternalInt32ElementsAccessor
+//     - ExternalUint32ElementsAccessor
+//     - ExternalFloat32ElementsAccessor
+//     - ExternalFloat64ElementsAccessor
+//     - ExternalUint8ClampedElementsAccessor
 //     - FixedUint8ElementsAccessor
 //     - FixedInt8ElementsAccessor
 //     - FixedUint16ElementsAccessor
@@ -70,6 +79,23 @@ static const int kPackedSizeNotKnown = -1;
     FixedArray)                                                               \
   V(SlowSloppyArgumentsElementsAccessor, SLOW_SLOPPY_ARGUMENTS_ELEMENTS,      \
     FixedArray)                                                               \
+  V(ExternalInt8ElementsAccessor, EXTERNAL_INT8_ELEMENTS, ExternalInt8Array)  \
+  V(ExternalUint8ElementsAccessor, EXTERNAL_UINT8_ELEMENTS,                   \
+    ExternalUint8Array)                                                       \
+  V(ExternalInt16ElementsAccessor, EXTERNAL_INT16_ELEMENTS,                   \
+    ExternalInt16Array)                                                       \
+  V(ExternalUint16ElementsAccessor, EXTERNAL_UINT16_ELEMENTS,                 \
+    ExternalUint16Array)                                                      \
+  V(ExternalInt32ElementsAccessor, EXTERNAL_INT32_ELEMENTS,                   \
+    ExternalInt32Array)                                                       \
+  V(ExternalUint32ElementsAccessor, EXTERNAL_UINT32_ELEMENTS,                 \
+    ExternalUint32Array)                                                      \
+  V(ExternalFloat32ElementsAccessor, EXTERNAL_FLOAT32_ELEMENTS,               \
+    ExternalFloat32Array)                                                     \
+  V(ExternalFloat64ElementsAccessor, EXTERNAL_FLOAT64_ELEMENTS,               \
+    ExternalFloat64Array)                                                     \
+  V(ExternalUint8ClampedElementsAccessor, EXTERNAL_UINT8_CLAMPED_ELEMENTS,    \
+    ExternalUint8ClampedArray)                                                \
   V(FixedUint8ElementsAccessor, UINT8_ELEMENTS, FixedUint8Array)              \
   V(FixedInt8ElementsAccessor, INT8_ELEMENTS, FixedInt8Array)                 \
   V(FixedUint16ElementsAccessor, UINT16_ELEMENTS, FixedUint16Array)           \
@@ -1192,6 +1218,7 @@ class FastSmiOrObjectElementsAccessor
       case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
         UNREACHABLE();
 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
+      case EXTERNAL_##TYPE##_ELEMENTS:                                        \
       case TYPE##_ELEMENTS:                                                   \
         UNREACHABLE();
       TYPED_ARRAYS(TYPED_ARRAY_CASE)
@@ -1288,6 +1315,7 @@ class FastDoubleElementsAccessor
         UNREACHABLE();
 
 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
+      case EXTERNAL_##TYPE##_ELEMENTS:                                        \
       case TYPE##_ELEMENTS:                                                   \
         UNREACHABLE();
       TYPED_ARRAYS(TYPED_ARRAY_CASE)
@@ -1378,6 +1406,13 @@ class TypedElementsAccessor
 
 
 
+#define EXTERNAL_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype, size)    \
+  typedef TypedElementsAccessor<EXTERNAL_##TYPE##_ELEMENTS>          \
+      External##Type##ElementsAccessor;
+
+TYPED_ARRAYS(EXTERNAL_ELEMENTS_ACCESSOR)
+#undef EXTERNAL_ELEMENTS_ACCESSOR
+
 #define FIXED_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype, size)       \
   typedef TypedElementsAccessor<TYPE##_ELEMENTS >                    \
       Fixed##Type##ElementsAccessor;
index 1d594d3eb5a6eda62470d908f7669c9b30028cbe..e2a5e05693a1202c1f1a41b1ccc7bb47d78580ee 100644 (file)
@@ -883,14 +883,18 @@ Handle<BytecodeArray> Factory::NewBytecodeArray(int length,
 }
 
 
-Handle<FixedTypedArrayBase> Factory::NewFixedTypedArrayWithExternalPointer(
-    int length, ExternalArrayType array_type, void* external_pointer,
-    PretenureFlag pretenure) {
+Handle<ExternalArray> Factory::NewExternalArray(int length,
+                                                ExternalArrayType array_type,
+                                                void* external_pointer,
+                                                PretenureFlag pretenure) {
   DCHECK(0 <= length && length <= Smi::kMaxValue);
   CALL_HEAP_FUNCTION(
-      isolate(), isolate()->heap()->AllocateFixedTypedArrayWithExternalPointer(
-                     length, array_type, external_pointer, pretenure),
-      FixedTypedArrayBase);
+      isolate(),
+      isolate()->heap()->AllocateExternalArray(length,
+                                               array_type,
+                                               external_pointer,
+                                               pretenure),
+      ExternalArray);
 }
 
 
@@ -1761,11 +1765,11 @@ ElementsKind GetExternalArrayElementsKind(ExternalArrayType type) {
   switch (type) {
 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
   case kExternal##Type##Array:                          \
-    return TYPE##_ELEMENTS;
+    return EXTERNAL_##TYPE##_ELEMENTS;
     TYPED_ARRAYS(TYPED_ARRAY_CASE)
   }
   UNREACHABLE();
-  return FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND;
+  return FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND;
 #undef TYPED_ARRAY_CASE
 }
 
@@ -1907,7 +1911,7 @@ Handle<JSTypedArray> Factory::NewJSTypedArray(ExternalArrayType type,
   Handle<Object> length_object = NewNumberFromSize(length);
   obj->set_length(*length_object);
 
-  Handle<FixedTypedArrayBase> elements = NewFixedTypedArrayWithExternalPointer(
+  Handle<ExternalArray> elements = NewExternalArray(
       static_cast<int>(length), type,
       static_cast<uint8_t*>(buffer->backing_store()) + byte_offset);
   Handle<Map> map = JSObject::GetElementsTransitionMap(obj, elements_kind);
index 9d42130ee1a85bc1facfd865240e0b5c70a512d1..1253779a1bb3071185ebd9cb124ff9fd276dcb21 100644 (file)
@@ -286,8 +286,10 @@ class Factory final {
   Handle<BytecodeArray> NewBytecodeArray(int length, const byte* raw_bytecodes,
                                          int frame_size);
 
-  Handle<FixedTypedArrayBase> NewFixedTypedArrayWithExternalPointer(
-      int length, ExternalArrayType array_type, void* external_pointer,
+  Handle<ExternalArray> NewExternalArray(
+      int length,
+      ExternalArrayType array_type,
+      void* external_pointer,
       PretenureFlag pretenure = NOT_TENURED);
 
   Handle<FixedTypedArrayBase> NewFixedTypedArray(
index 34936fb8e8f72dfb43e4c2562d76f57560e7a8f9..63916a268fb237d17afcc1c5ef7eac3b24863b88 100644 (file)
@@ -856,8 +856,10 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) {
     return AddEntry(object, HeapEntry::kHidden, "system / NativeContext");
   } else if (object->IsContext()) {
     return AddEntry(object, HeapEntry::kObject, "system / Context");
-  } else if (object->IsFixedArray() || object->IsFixedDoubleArray() ||
-             object->IsByteArray()) {
+  } else if (object->IsFixedArray() ||
+             object->IsFixedDoubleArray() ||
+             object->IsByteArray() ||
+             object->IsExternalArray()) {
     return AddEntry(object, HeapEntry::kArray, "");
   } else if (object->IsHeapNumber()) {
     return AddEntry(object, HeapEntry::kHeapNumber, "number");
index b75c6f7bc6083d0990089dd6f3aec50e6b057b99..80b28d195bf73d6055ac1ef3c6fa74200de866ec 100644 (file)
@@ -2500,8 +2500,7 @@ class ScavengingVisitor : public StaticVisitorBase {
     DCHECK(map_word.IsForwardingAddress());
     FixedTypedArrayBase* target =
         reinterpret_cast<FixedTypedArrayBase*>(map_word.ToForwardingAddress());
-    if (target->base_pointer() != Smi::FromInt(0))
-      target->set_base_pointer(target, SKIP_WRITE_BARRIER);
+    target->set_base_pointer(target, SKIP_WRITE_BARRIER);
   }
 
 
@@ -2514,8 +2513,7 @@ class ScavengingVisitor : public StaticVisitorBase {
     DCHECK(map_word.IsForwardingAddress());
     FixedTypedArrayBase* target =
         reinterpret_cast<FixedTypedArrayBase*>(map_word.ToForwardingAddress());
-    if (target->base_pointer() != Smi::FromInt(0))
-      target->set_base_pointer(target, SKIP_WRITE_BARRIER);
+    target->set_base_pointer(target, SKIP_WRITE_BARRIER);
   }
 
 
@@ -3006,6 +3004,13 @@ bool Heap::CreateInitialMaps() {
     ALLOCATE_VARSIZE_MAP(BYTECODE_ARRAY_TYPE, bytecode_array)
     ALLOCATE_VARSIZE_MAP(FREE_SPACE_TYPE, free_space)
 
+#define ALLOCATE_EXTERNAL_ARRAY_MAP(Type, type, TYPE, ctype, size) \
+  ALLOCATE_MAP(EXTERNAL_##TYPE##_ARRAY_TYPE, ExternalArray::kSize, \
+               external_##type##_array)
+
+    TYPED_ARRAYS(ALLOCATE_EXTERNAL_ARRAY_MAP)
+#undef ALLOCATE_EXTERNAL_ARRAY_MAP
+
 #define ALLOCATE_FIXED_TYPED_ARRAY_MAP(Type, type, TYPE, ctype, size) \
   ALLOCATE_VARSIZE_MAP(FIXED_##TYPE##_ARRAY_TYPE, fixed_##type##_array)
 
@@ -3071,6 +3076,17 @@ bool Heap::CreateInitialMaps() {
       set_empty_bytecode_array(bytecode_array);
     }
 
+#define ALLOCATE_EMPTY_EXTERNAL_ARRAY(Type, type, TYPE, ctype, size)  \
+  {                                                                   \
+    ExternalArray* obj;                                               \
+    if (!AllocateEmptyExternalArray(kExternal##Type##Array).To(&obj)) \
+      return false;                                                   \
+    set_empty_external_##type##_array(obj);                           \
+  }
+
+    TYPED_ARRAYS(ALLOCATE_EMPTY_EXTERNAL_ARRAY)
+#undef ALLOCATE_EMPTY_EXTERNAL_ARRAY
+
 #define ALLOCATE_EMPTY_FIXED_TYPED_ARRAY(Type, type, TYPE, ctype, size) \
   {                                                                     \
     FixedTypedArrayBase* obj;                                           \
@@ -3686,6 +3702,27 @@ void Heap::AddAllocationSiteToScratchpad(AllocationSite* site,
 }
 
 
+Map* Heap::MapForExternalArrayType(ExternalArrayType array_type) {
+  return Map::cast(roots_[RootIndexForExternalArrayType(array_type)]);
+}
+
+
+Heap::RootListIndex Heap::RootIndexForExternalArrayType(
+    ExternalArrayType array_type) {
+  switch (array_type) {
+#define ARRAY_TYPE_TO_ROOT_INDEX(Type, type, TYPE, ctype, size) \
+  case kExternal##Type##Array:                                  \
+    return kExternal##Type##ArrayMapRootIndex;
+
+    TYPED_ARRAYS(ARRAY_TYPE_TO_ROOT_INDEX)
+#undef ARRAY_TYPE_TO_ROOT_INDEX
+
+    default:
+      UNREACHABLE();
+      return kUndefinedValueRootIndex;
+  }
+}
+
 
 Map* Heap::MapForFixedTypedArray(ExternalArrayType array_type) {
   return Map::cast(roots_[RootIndexForFixedTypedArray(array_type)]);
@@ -3709,6 +3746,23 @@ Heap::RootListIndex Heap::RootIndexForFixedTypedArray(
 }
 
 
+Heap::RootListIndex Heap::RootIndexForEmptyExternalArray(
+    ElementsKind elementsKind) {
+  switch (elementsKind) {
+#define ELEMENT_KIND_TO_ROOT_INDEX(Type, type, TYPE, ctype, size) \
+  case EXTERNAL_##TYPE##_ELEMENTS:                                \
+    return kEmptyExternal##Type##ArrayRootIndex;
+
+    TYPED_ARRAYS(ELEMENT_KIND_TO_ROOT_INDEX)
+#undef ELEMENT_KIND_TO_ROOT_INDEX
+
+    default:
+      UNREACHABLE();
+      return kUndefinedValueRootIndex;
+  }
+}
+
+
 Heap::RootListIndex Heap::RootIndexForEmptyFixedTypedArray(
     ElementsKind elementsKind) {
   switch (elementsKind) {
@@ -3725,6 +3779,12 @@ Heap::RootListIndex Heap::RootIndexForEmptyFixedTypedArray(
 }
 
 
+ExternalArray* Heap::EmptyExternalArrayForMap(Map* map) {
+  return ExternalArray::cast(
+      roots_[RootIndexForEmptyExternalArray(map->elements_kind())]);
+}
+
+
 FixedTypedArrayBase* Heap::EmptyFixedTypedArrayForMap(Map* map) {
   return FixedTypedArrayBase::cast(
       roots_[RootIndexForEmptyFixedTypedArray(map->elements_kind())]);
@@ -3945,10 +4005,11 @@ void Heap::RightTrimFixedArray(FixedArrayBase* object, int elements_to_trim) {
 }
 
 
-AllocationResult Heap::AllocateFixedTypedArrayWithExternalPointer(
-    int length, ExternalArrayType array_type, void* external_pointer,
-    PretenureFlag pretenure) {
-  int size = FixedTypedArrayBase::kHeaderSize;
+AllocationResult Heap::AllocateExternalArray(int length,
+                                             ExternalArrayType array_type,
+                                             void* external_pointer,
+                                             PretenureFlag pretenure) {
+  int size = ExternalArray::kSize;
   AllocationSpace space = SelectSpace(size, pretenure);
   HeapObject* result;
   {
@@ -3956,12 +4017,10 @@ AllocationResult Heap::AllocateFixedTypedArrayWithExternalPointer(
     if (!allocation.To(&result)) return allocation;
   }
 
-  result->set_map_no_write_barrier(MapForFixedTypedArray(array_type));
-  FixedTypedArrayBase* elements = FixedTypedArrayBase::cast(result);
-  elements->set_base_pointer(Smi::FromInt(0), SKIP_WRITE_BARRIER);
-  elements->set_external_pointer(external_pointer, SKIP_WRITE_BARRIER);
-  elements->set_length(length);
-  return elements;
+  result->set_map_no_write_barrier(MapForExternalArrayType(array_type));
+  ExternalArray::cast(result)->set_length(length);
+  ExternalArray::cast(result)->set_external_pointer(external_pointer);
+  return result;
 }
 
 static void ForFixedTypedArray(ExternalArrayType array_type, int* element_size,
@@ -4001,7 +4060,7 @@ AllocationResult Heap::AllocateFixedTypedArray(int length,
       array_type == kExternalFloat64Array ? kDoubleAligned : kWordAligned);
   if (!allocation.To(&object)) return allocation;
 
-  object->set_map_no_write_barrier(MapForFixedTypedArray(array_type));
+  object->set_map(MapForFixedTypedArray(array_type));
   FixedTypedArrayBase* elements = FixedTypedArrayBase::cast(object);
   elements->set_base_pointer(elements, SKIP_WRITE_BARRIER);
   elements->set_external_pointer(
@@ -4216,7 +4275,8 @@ AllocationResult Heap::AllocateJSObjectFromMap(
 
   // Initialize the JSObject.
   InitializeJSObjectFromMap(js_obj, properties, map);
-  DCHECK(js_obj->HasFastElements() || js_obj->HasFixedTypedArrayElements());
+  DCHECK(js_obj->HasFastElements() || js_obj->HasExternalArrayElements() ||
+         js_obj->HasFixedTypedArrayElements());
   return js_obj;
 }
 
@@ -4508,6 +4568,12 @@ AllocationResult Heap::AllocateEmptyFixedArray() {
 }
 
 
+AllocationResult Heap::AllocateEmptyExternalArray(
+    ExternalArrayType array_type) {
+  return AllocateExternalArray(0, array_type, NULL, TENURED);
+}
+
+
 AllocationResult Heap::CopyAndTenureFixedCOWArray(FixedArray* src) {
   if (!InNewSpace(src)) {
     return src;
index 15577ee02390be901caa9e71bd30cfca41fe2889..edc3d2c8dfe9b9359070b12fd91410e8c7b4ebfd 100644 (file)
@@ -105,6 +105,25 @@ namespace internal {
   V(Map, short_external_one_byte_internalized_string_map,                      \
     ShortExternalOneByteInternalizedStringMap)                                 \
   V(Map, short_external_one_byte_string_map, ShortExternalOneByteStringMap)    \
+  V(Map, external_int8_array_map, ExternalInt8ArrayMap)                        \
+  V(Map, external_uint8_array_map, ExternalUint8ArrayMap)                      \
+  V(Map, external_int16_array_map, ExternalInt16ArrayMap)                      \
+  V(Map, external_uint16_array_map, ExternalUint16ArrayMap)                    \
+  V(Map, external_int32_array_map, ExternalInt32ArrayMap)                      \
+  V(Map, external_uint32_array_map, ExternalUint32ArrayMap)                    \
+  V(Map, external_float32_array_map, ExternalFloat32ArrayMap)                  \
+  V(Map, external_float64_array_map, ExternalFloat64ArrayMap)                  \
+  V(Map, external_uint8_clamped_array_map, ExternalUint8ClampedArrayMap)       \
+  V(ExternalArray, empty_external_int8_array, EmptyExternalInt8Array)          \
+  V(ExternalArray, empty_external_uint8_array, EmptyExternalUint8Array)        \
+  V(ExternalArray, empty_external_int16_array, EmptyExternalInt16Array)        \
+  V(ExternalArray, empty_external_uint16_array, EmptyExternalUint16Array)      \
+  V(ExternalArray, empty_external_int32_array, EmptyExternalInt32Array)        \
+  V(ExternalArray, empty_external_uint32_array, EmptyExternalUint32Array)      \
+  V(ExternalArray, empty_external_float32_array, EmptyExternalFloat32Array)    \
+  V(ExternalArray, empty_external_float64_array, EmptyExternalFloat64Array)    \
+  V(ExternalArray, empty_external_uint8_clamped_array,                         \
+    EmptyExternalUint8ClampedArray)                                            \
   V(Map, fixed_uint8_array_map, FixedUint8ArrayMap)                            \
   V(Map, fixed_int8_array_map, FixedInt8ArrayMap)                              \
   V(Map, fixed_uint16_array_map, FixedUint16ArrayMap)                          \
@@ -1250,7 +1269,12 @@ class Heap {
   Map* MapForFixedTypedArray(ExternalArrayType array_type);
   RootListIndex RootIndexForFixedTypedArray(ExternalArrayType array_type);
 
+  Map* MapForExternalArrayType(ExternalArrayType array_type);
+  RootListIndex RootIndexForExternalArrayType(ExternalArrayType array_type);
+
+  RootListIndex RootIndexForEmptyExternalArray(ElementsKind kind);
   RootListIndex RootIndexForEmptyFixedTypedArray(ElementsKind kind);
+  ExternalArray* EmptyExternalArrayForMap(Map* map);
   FixedTypedArrayBase* EmptyFixedTypedArrayForMap(Map* map);
 
   void RecordStats(HeapStats* stats, bool take_snapshot = false);
@@ -2022,9 +2046,9 @@ class Heap {
   MUST_USE_RESULT AllocationResult AllocateSymbol();
 
   // Allocates an external array of the specified length and type.
-  MUST_USE_RESULT AllocationResult AllocateFixedTypedArrayWithExternalPointer(
-      int length, ExternalArrayType array_type, void* external_pointer,
-      PretenureFlag pretenure);
+  MUST_USE_RESULT AllocationResult
+      AllocateExternalArray(int length, ExternalArrayType array_type,
+                            void* external_pointer, PretenureFlag pretenure);
 
   // Allocates a fixed typed array of the specified length and type.
   MUST_USE_RESULT AllocationResult
@@ -2052,6 +2076,10 @@ class Heap {
   // Allocate empty fixed array.
   MUST_USE_RESULT AllocationResult AllocateEmptyFixedArray();
 
+  // Allocate empty external array of given type.
+  MUST_USE_RESULT AllocationResult
+      AllocateEmptyExternalArray(ExternalArrayType array_type);
+
   // Allocate empty fixed typed array of given type.
   MUST_USE_RESULT AllocationResult
       AllocateEmptyFixedTypedArray(ExternalArrayType array_type);
index 70f26a504a7f743de883094653103b9158fd4344..8de0da96210a472adc51cbf00071da6b6189c81d 100644 (file)
@@ -139,8 +139,13 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId(
     case HEAP_NUMBER_TYPE:
     case MUTABLE_HEAP_NUMBER_TYPE:
     case FLOAT32X4_TYPE:
+#define EXTERNAL_ARRAY_CASE(Type, type, TYPE, ctype, size) \
+  case EXTERNAL_##TYPE##_ARRAY_TYPE:
+
+      TYPED_ARRAYS(EXTERNAL_ARRAY_CASE)
       return GetVisitorIdForSize(kVisitDataObject, kVisitDataObjectGeneric,
                                  instance_size, has_unboxed_fields);
+#undef EXTERNAL_ARRAY_CASE
 
     case FIXED_UINT8_ARRAY_TYPE:
     case FIXED_INT8_ARRAY_TYPE:
index 10f4bf3f57cf89d46b6d8d051505821d5c21063e..24259c8b7bb4b1251851a6e336f16877c6df81fc 100644 (file)
@@ -3207,13 +3207,18 @@ Range* HLoadNamedField::InferRange(Zone* zone) {
 
 Range* HLoadKeyed::InferRange(Zone* zone) {
   switch (elements_kind()) {
+    case EXTERNAL_INT8_ELEMENTS:
     case INT8_ELEMENTS:
       return new(zone) Range(kMinInt8, kMaxInt8);
+    case EXTERNAL_UINT8_ELEMENTS:
+    case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
     case UINT8_ELEMENTS:
     case UINT8_CLAMPED_ELEMENTS:
       return new(zone) Range(kMinUInt8, kMaxUInt8);
+    case EXTERNAL_INT16_ELEMENTS:
     case INT16_ELEMENTS:
       return new(zone) Range(kMinInt16, kMaxInt16);
+    case EXTERNAL_UINT16_ELEMENTS:
     case UINT16_ELEMENTS:
       return new(zone) Range(kMinUInt16, kMaxUInt16);
     default:
@@ -3456,11 +3461,11 @@ std::ostream& HLoadNamedGeneric::PrintDataTo(
 
 
 std::ostream& HLoadKeyed::PrintDataTo(std::ostream& os) const {  // NOLINT
-  if (!is_fixed_typed_array()) {
+  if (!is_external()) {
     os << NameOf(elements());
   } else {
-    DCHECK(elements_kind() >= FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND &&
-           elements_kind() <= LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
+    DCHECK(elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND &&
+           elements_kind() <= LAST_EXTERNAL_ARRAY_ELEMENTS_KIND);
     os << NameOf(elements()) << "." << ElementsKindToString(elements_kind());
   }
 
@@ -3495,7 +3500,7 @@ bool HLoadKeyed::UsesMustHandleHole() const {
     return false;
   }
 
-  if (IsFixedTypedArrayElementsKind(elements_kind())) {
+  if (IsExternalArrayElementsKind(elements_kind())) {
     return false;
   }
 
@@ -3535,7 +3540,7 @@ bool HLoadKeyed::RequiresHoleCheck() const {
     return false;
   }
 
-  if (IsFixedTypedArrayElementsKind(elements_kind())) {
+  if (IsExternalArrayElementsKind(elements_kind())) {
     return false;
   }
 
@@ -3610,11 +3615,11 @@ std::ostream& HStoreNamedField::PrintDataTo(std::ostream& os) const {  // NOLINT
 
 
 std::ostream& HStoreKeyed::PrintDataTo(std::ostream& os) const {  // NOLINT
-  if (!is_fixed_typed_array()) {
+  if (!is_external()) {
     os << NameOf(elements());
   } else {
-    DCHECK(elements_kind() >= FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND &&
-           elements_kind() <= LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
+    DCHECK(elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND &&
+           elements_kind() <= LAST_EXTERNAL_ARRAY_ELEMENTS_KIND);
     os << NameOf(elements()) << "." << ElementsKindToString(elements_kind());
   }
 
@@ -3978,7 +3983,8 @@ bool HStoreKeyed::NeedsCanonicalization() {
   switch (value()->opcode()) {
     case kLoadKeyed: {
       ElementsKind load_kind = HLoadKeyed::cast(value())->elements_kind();
-      return IsFixedFloatElementsKind(load_kind);
+      return IsExternalFloatOrDoubleElementsKind(load_kind) ||
+             IsFixedFloatElementsKind(load_kind);
     }
     case kChange: {
       Representation from = HChange::cast(value())->from();
index 8cf65d5c8e3f3ed2512c7757d8f80fb03f6d9d23..3d3c56cc4063d4ad4859b060a9509c92be84da58 100644 (file)
@@ -6248,6 +6248,11 @@ class HObjectAccess final {
         JSArrayBuffer::kBitFieldSlot, Representation::Smi());
   }
 
+  static HObjectAccess ForExternalArrayExternalPointer() {
+    return HObjectAccess::ForObservableJSObjectOffset(
+        ExternalArray::kExternalPointerOffset, Representation::External());
+  }
+
   static HObjectAccess ForJSArrayBufferViewBuffer() {
     return HObjectAccess::ForObservableJSObjectOffset(
         JSArrayBufferView::kBufferOffset);
@@ -6617,9 +6622,15 @@ class HLoadKeyed final : public HTemplateInstruction<3>,
   DECLARE_INSTRUCTION_FACTORY_P6(HLoadKeyed, HValue*, HValue*, HValue*,
                                  ElementsKind, LoadKeyedHoleMode, int);
 
+  bool is_external() const {
+    return IsExternalArrayElementsKind(elements_kind());
+  }
   bool is_fixed_typed_array() const {
     return IsFixedTypedArrayElementsKind(elements_kind());
   }
+  bool is_typed_elements() const {
+    return is_external() || is_fixed_typed_array();
+  }
   HValue* elements() const { return OperandAt(0); }
   HValue* key() const { return OperandAt(1); }
   HValue* dependency() const {
@@ -6650,8 +6661,8 @@ class HLoadKeyed final : public HTemplateInstruction<3>,
     // kind_fixed_typed_array:    external[int32] (none)
     // kind_external:             external[int32] (none)
     if (index == 0) {
-      return is_fixed_typed_array() ? Representation::External()
-                                    : Representation::Tagged();
+      return is_typed_elements() ? Representation::External()
+                                 : Representation::Tagged();
     }
     if (index == 1) {
       return ArrayInstructionInterface::KeyedAccessIndexRequirement(
@@ -6700,7 +6711,7 @@ class HLoadKeyed final : public HTemplateInstruction<3>,
     SetOperandAt(1, key);
     SetOperandAt(2, dependency != NULL ? dependency : obj);
 
-    if (!is_fixed_typed_array()) {
+    if (!is_typed_elements()) {
       // I can detect the case between storing double (holey and fast) and
       // smi/object by looking at elements_kind_.
       DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
@@ -6726,15 +6737,18 @@ class HLoadKeyed final : public HTemplateInstruction<3>,
         SetDependsOnFlag(kDoubleArrayElements);
       }
     } else {
-      if (elements_kind == FLOAT32_ELEMENTS ||
+      if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+          elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
+          elements_kind == FLOAT32_ELEMENTS ||
           elements_kind == FLOAT64_ELEMENTS) {
         set_representation(Representation::Double());
       } else {
         set_representation(Representation::Integer32());
       }
 
-      if (is_fixed_typed_array()) {
+      if (is_external()) {
         SetDependsOnFlag(kExternalMemory);
+      } else if (is_fixed_typed_array()) {
         SetDependsOnFlag(kTypedArrayElements);
       } else {
         UNREACHABLE();
@@ -7109,8 +7123,8 @@ class HStoreKeyed final : public HTemplateInstruction<3>,
     // kind_fixed_typed_array:  tagged[int32] = (double | int32)
     // kind_external:           external[int32] = (double | int32)
     if (index == 0) {
-      return is_fixed_typed_array() ? Representation::External()
-                                    : Representation::Tagged();
+      return is_typed_elements() ? Representation::External()
+                                 : Representation::Tagged();
     } else if (index == 1) {
       return ArrayInstructionInterface::KeyedAccessIndexRequirement(
           OperandAt(1)->representation());
@@ -7135,16 +7149,24 @@ class HStoreKeyed final : public HTemplateInstruction<3>,
       return Representation::Smi();
     }
 
-    if (IsFixedTypedArrayElementsKind(kind)) {
-      return Representation::Integer32();
-    }
-    return Representation::Tagged();
+    return IsExternalArrayElementsKind(kind) ||
+                   IsFixedTypedArrayElementsKind(kind)
+               ? Representation::Integer32()
+               : Representation::Tagged();
+  }
+
+  bool is_external() const {
+    return IsExternalArrayElementsKind(elements_kind());
   }
 
   bool is_fixed_typed_array() const {
     return IsFixedTypedArrayElementsKind(elements_kind());
   }
 
+  bool is_typed_elements() const {
+    return is_external() || is_fixed_typed_array();
+  }
+
   Representation observed_input_representation(int index) override {
     if (index < 2) return RequiredInputRepresentation(index);
     if (IsUninitialized()) {
@@ -7234,20 +7256,25 @@ class HStoreKeyed final : public HTemplateInstruction<3>,
       SetFlag(kTrackSideEffectDominators);
       SetDependsOnFlag(kNewSpacePromotion);
     }
-    if (IsFastDoubleElementsKind(elements_kind)) {
+    if (is_external()) {
+      SetChangesFlag(kExternalMemory);
+      SetFlag(kAllowUndefinedAsNaN);
+    } else if (IsFastDoubleElementsKind(elements_kind)) {
       SetChangesFlag(kDoubleArrayElements);
     } else if (IsFastSmiElementsKind(elements_kind)) {
       SetChangesFlag(kArrayElements);
     } else if (is_fixed_typed_array()) {
       SetChangesFlag(kTypedArrayElements);
-      SetChangesFlag(kExternalMemory);
       SetFlag(kAllowUndefinedAsNaN);
     } else {
       SetChangesFlag(kArrayElements);
     }
 
-    // {UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
-    if (elements_kind >= UINT8_ELEMENTS && elements_kind <= INT32_ELEMENTS) {
+    // EXTERNAL_{UNSIGNED_,}{BYTE,SHORT,INT}_ELEMENTS are truncating.
+    if ((elements_kind >= EXTERNAL_INT8_ELEMENTS &&
+        elements_kind <= EXTERNAL_UINT32_ELEMENTS) ||
+        (elements_kind >= UINT8_ELEMENTS &&
+        elements_kind <= INT32_ELEMENTS)) {
       SetFlag(kTruncatingToInt32);
     }
   }
index c6cbc9bc357988a8e46fcb460b708cc67ddb023b..37f19ebdaff370f19d4b8e801ed9cbc51be9de2a 100644 (file)
@@ -10,6 +10,10 @@ namespace internal {
 
 static bool IsUnsignedLoad(HLoadKeyed* instr) {
   switch (instr->elements_kind()) {
+    case EXTERNAL_UINT8_ELEMENTS:
+    case EXTERNAL_UINT16_ELEMENTS:
+    case EXTERNAL_UINT32_ELEMENTS:
+    case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
     case UINT8_ELEMENTS:
     case UINT16_ELEMENTS:
     case UINT32_ELEMENTS:
@@ -46,14 +50,14 @@ bool HUint32AnalysisPhase::IsSafeUint32Use(HValue* val, HValue* use) {
     return true;
   } else if (use->IsStoreKeyed()) {
     HStoreKeyed* store = HStoreKeyed::cast(use);
-    if (store->is_fixed_typed_array()) {
+    if (store->is_external()) {
       // Storing a value into an external integer array is a bit level
       // operation.
       if (store->value() == val) {
         // Clamping or a conversion to double should have beed inserted.
-        DCHECK(store->elements_kind() != UINT8_CLAMPED_ELEMENTS);
-        DCHECK(store->elements_kind() != FLOAT32_ELEMENTS);
-        DCHECK(store->elements_kind() != FLOAT64_ELEMENTS);
+        DCHECK(store->elements_kind() != EXTERNAL_UINT8_CLAMPED_ELEMENTS);
+        DCHECK(store->elements_kind() != EXTERNAL_FLOAT32_ELEMENTS);
+        DCHECK(store->elements_kind() != EXTERNAL_FLOAT64_ELEMENTS);
         return true;
       }
     }
index abfe9cab2b307826353dcff2bde76cb104a56c90..f4bd4179790f34409068a04ce518c46c6ecca4c7 100644 (file)
@@ -2416,7 +2416,9 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
     KeyedAccessStoreMode store_mode) {
   DCHECK(top_info()->IsStub() || checked_object->IsCompareMap() ||
          checked_object->IsCheckMaps());
-  DCHECK(!IsFixedTypedArrayElementsKind(elements_kind) || !is_js_array);
+  DCHECK((!IsExternalArrayElementsKind(elements_kind) &&
+              !IsFixedTypedArrayElementsKind(elements_kind)) ||
+         !is_js_array);
   // No GVNFlag is necessary for ElementsKind if there is an explicit dependency
   // on a HElementsTransition instruction. The flag can also be removed if the
   // map to check has FAST_HOLEY_ELEMENTS, since there can be no further
@@ -2447,17 +2449,24 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
   }
   length->set_type(HType::Smi());
   HValue* checked_key = NULL;
-  if (IsFixedTypedArrayElementsKind(elements_kind)) {
+  if (IsExternalArrayElementsKind(elements_kind) ||
+      IsFixedTypedArrayElementsKind(elements_kind)) {
     checked_object = Add<HCheckArrayBufferNotNeutered>(checked_object);
 
-    HValue* external_pointer = Add<HLoadNamedField>(
-        elements, nullptr,
-        HObjectAccess::ForFixedTypedArrayBaseExternalPointer());
-    HValue* base_pointer = Add<HLoadNamedField>(
-        elements, nullptr, HObjectAccess::ForFixedTypedArrayBaseBasePointer());
-    HValue* backing_store = AddUncasted<HAdd>(
-        external_pointer, base_pointer, Strength::WEAK, AddOfExternalAndTagged);
-
+    HValue* backing_store;
+    if (IsExternalArrayElementsKind(elements_kind)) {
+      backing_store = Add<HLoadNamedField>(
+          elements, nullptr, HObjectAccess::ForExternalArrayExternalPointer());
+    } else {
+      HValue* external_pointer = Add<HLoadNamedField>(
+          elements, nullptr,
+          HObjectAccess::ForFixedTypedArrayBaseExternalPointer());
+      HValue* base_pointer = Add<HLoadNamedField>(
+          elements, nullptr,
+          HObjectAccess::ForFixedTypedArrayBaseBasePointer());
+      backing_store = AddUncasted<HAdd>(external_pointer, base_pointer,
+                                        Strength::WEAK, AddOfExternalAndTagged);
+    }
     if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
       NoObservableSideEffectsScope no_effects(this);
       IfBuilder length_checker(this);
@@ -2689,7 +2698,8 @@ HInstruction* HGraphBuilder::AddElementAccess(
     LoadKeyedHoleMode load_mode) {
   if (access_type == STORE) {
     DCHECK(val != NULL);
-    if (elements_kind == UINT8_CLAMPED_ELEMENTS) {
+    if (elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS ||
+        elements_kind == UINT8_CLAMPED_ELEMENTS) {
       val = Add<HClampToUint8>(val);
     }
     return Add<HStoreKeyed>(elements, checked_key, val, elements_kind,
@@ -2700,7 +2710,8 @@ HInstruction* HGraphBuilder::AddElementAccess(
   DCHECK(val == NULL);
   HLoadKeyed* load = Add<HLoadKeyed>(
       elements, checked_key, dependency, elements_kind, load_mode);
-  if (elements_kind == UINT32_ELEMENTS) {
+  if (elements_kind == EXTERNAL_UINT32_ELEMENTS ||
+      elements_kind == UINT32_ELEMENTS) {
     graph()->RecordUint32Instruction(load);
   }
   return load;
@@ -7402,6 +7413,7 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
                                                 val));
     } else {
       DCHECK(IsFastElementsKind(elements_kind) ||
+             IsExternalArrayElementsKind(elements_kind) ||
              IsFixedTypedArrayElementsKind(elements_kind));
       LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
       // Happily, mapcompare is a checked object.
@@ -9936,14 +9948,14 @@ HValue* HOptimizedGraphBuilder::BuildAllocateExternalElements(
     bool is_zero_byte_offset,
     HValue* buffer, HValue* byte_offset, HValue* length) {
   Handle<Map> external_array_map(
-      isolate()->heap()->MapForFixedTypedArray(array_type));
+      isolate()->heap()->MapForExternalArrayType(array_type));
 
   // The HForceRepresentation is to prevent possible deopt on int-smi
   // conversion after allocation but before the new object fields are set.
   length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
-  HValue* elements = Add<HAllocate>(
-      Add<HConstant>(FixedTypedArrayBase::kHeaderSize), HType::HeapObject(),
-      NOT_TENURED, external_array_map->instance_type());
+  HValue* elements =
+      Add<HAllocate>(Add<HConstant>(ExternalArray::kSize), HType::HeapObject(),
+                     NOT_TENURED, external_array_map->instance_type());
 
   AddStoreMapConstant(elements, external_array_map);
   Add<HStoreNamedField>(elements,
@@ -9965,11 +9977,8 @@ HValue* HOptimizedGraphBuilder::BuildAllocateExternalElements(
   }
 
   Add<HStoreNamedField>(elements,
-                        HObjectAccess::ForFixedTypedArrayBaseBasePointer(),
-                        graph()->GetConstant0());
-  Add<HStoreNamedField>(elements,
-                        HObjectAccess::ForFixedTypedArrayBaseExternalPointer(),
-                        typed_array_start);
+      HObjectAccess::ForExternalArrayExternalPointer(),
+      typed_array_start);
 
   return elements;
 }
@@ -10116,10 +10125,13 @@ void HOptimizedGraphBuilder::GenerateTypedArrayInitialize(
   ExternalArrayType array_type =
       kExternalInt8Array;  // Bogus initialization.
   size_t element_size = 1;  // Bogus initialization.
+  ElementsKind external_elements_kind =  // Bogus initialization.
+      EXTERNAL_INT8_ELEMENTS;
   ElementsKind fixed_elements_kind =  // Bogus initialization.
       INT8_ELEMENTS;
   Runtime::ArrayIdToTypeAndSize(array_id,
       &array_type,
+      &external_elements_kind,
       &fixed_elements_kind,
       &element_size);
 
@@ -10144,8 +10156,8 @@ void HOptimizedGraphBuilder::GenerateTypedArrayInitialize(
     if (buffer != NULL) {
       elements = BuildAllocateExternalElements(
           array_type, is_zero_byte_offset, buffer, byte_offset, length);
-      Handle<Map> obj_map =
-          TypedArrayMap(isolate(), array_type, fixed_elements_kind);
+      Handle<Map> obj_map = TypedArrayMap(
+          isolate(), array_type, external_elements_kind);
       AddStoreMapConstant(obj, obj_map);
     } else {
       DCHECK(is_zero_byte_offset);
index 892193a3f8ba28d20603e7e1b4c5d6b47a16e74d..db2602c179c2d40eedeb1f864f38026ac21fb517 100644 (file)
@@ -3070,31 +3070,40 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
       instr->hydrogen()->key()->representation(),
       elements_kind,
       instr->base_offset()));
-  if (elements_kind == FLOAT32_ELEMENTS) {
+  if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+      elements_kind == FLOAT32_ELEMENTS) {
     XMMRegister result(ToDoubleRegister(instr->result()));
     __ movss(result, operand);
     __ cvtss2sd(result, result);
-  } else if (elements_kind == FLOAT64_ELEMENTS) {
+  } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
+             elements_kind == FLOAT64_ELEMENTS) {
     __ movsd(ToDoubleRegister(instr->result()), operand);
   } else {
     Register result(ToRegister(instr->result()));
     switch (elements_kind) {
+      case EXTERNAL_INT8_ELEMENTS:
       case INT8_ELEMENTS:
         __ movsx_b(result, operand);
         break;
+      case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
+      case EXTERNAL_UINT8_ELEMENTS:
       case UINT8_ELEMENTS:
       case UINT8_CLAMPED_ELEMENTS:
         __ movzx_b(result, operand);
         break;
+      case EXTERNAL_INT16_ELEMENTS:
       case INT16_ELEMENTS:
         __ movsx_w(result, operand);
         break;
+      case EXTERNAL_UINT16_ELEMENTS:
       case UINT16_ELEMENTS:
         __ movzx_w(result, operand);
         break;
+      case EXTERNAL_INT32_ELEMENTS:
       case INT32_ELEMENTS:
         __ mov(result, operand);
         break;
+      case EXTERNAL_UINT32_ELEMENTS:
       case UINT32_ELEMENTS:
         __ mov(result, operand);
         if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
@@ -3102,6 +3111,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
           DeoptimizeIf(negative, instr, Deoptimizer::kNegativeValue);
         }
         break;
+      case EXTERNAL_FLOAT32_ELEMENTS:
+      case EXTERNAL_FLOAT64_ELEMENTS:
       case FLOAT32_ELEMENTS:
       case FLOAT64_ELEMENTS:
       case FAST_SMI_ELEMENTS:
@@ -3181,7 +3192,7 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
 
 
 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
-  if (instr->is_fixed_typed_array()) {
+  if (instr->is_typed_elements()) {
     DoLoadKeyedExternalArray(instr);
   } else if (instr->hydrogen()->representation().IsDouble()) {
     DoLoadKeyedFixedDoubleArray(instr);
@@ -4196,28 +4207,39 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
       instr->hydrogen()->key()->representation(),
       elements_kind,
       instr->base_offset()));
-  if (elements_kind == FLOAT32_ELEMENTS) {
+  if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+      elements_kind == FLOAT32_ELEMENTS) {
     XMMRegister xmm_scratch = double_scratch0();
     __ cvtsd2ss(xmm_scratch, ToDoubleRegister(instr->value()));
     __ movss(operand, xmm_scratch);
-  } else if (elements_kind == FLOAT64_ELEMENTS) {
+  } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
+             elements_kind == FLOAT64_ELEMENTS) {
     __ movsd(operand, ToDoubleRegister(instr->value()));
   } else {
     Register value = ToRegister(instr->value());
     switch (elements_kind) {
+      case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
+      case EXTERNAL_UINT8_ELEMENTS:
+      case EXTERNAL_INT8_ELEMENTS:
       case UINT8_ELEMENTS:
       case INT8_ELEMENTS:
       case UINT8_CLAMPED_ELEMENTS:
         __ mov_b(operand, value);
         break;
+      case EXTERNAL_INT16_ELEMENTS:
+      case EXTERNAL_UINT16_ELEMENTS:
       case UINT16_ELEMENTS:
       case INT16_ELEMENTS:
         __ mov_w(operand, value);
         break;
+      case EXTERNAL_INT32_ELEMENTS:
+      case EXTERNAL_UINT32_ELEMENTS:
       case UINT32_ELEMENTS:
       case INT32_ELEMENTS:
         __ mov(operand, value);
         break;
+      case EXTERNAL_FLOAT32_ELEMENTS:
+      case EXTERNAL_FLOAT64_ELEMENTS:
       case FLOAT32_ELEMENTS:
       case FLOAT64_ELEMENTS:
       case FAST_SMI_ELEMENTS:
@@ -4303,7 +4325,7 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
 
 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
   // By cases...external, fast-double, fast
-  if (instr->is_fixed_typed_array()) {
+  if (instr->is_typed_elements()) {
     DoStoreKeyedExternalArray(instr);
   } else if (instr->hydrogen()->value()->representation().IsDouble()) {
     DoStoreKeyedFixedDoubleArray(instr);
index e00b43d6fb2f21490ac325c8cf3c7d8b9384471b..eeccdd0502478b7d5f6eb9fba1b6b698330fab31 100644 (file)
@@ -2242,7 +2242,7 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
       : UseRegisterOrConstantAtStart(instr->key());
   LInstruction* result = NULL;
 
-  if (!instr->is_fixed_typed_array()) {
+  if (!instr->is_typed_elements()) {
     LOperand* obj = UseRegisterAtStart(instr->elements());
     result = DefineAsRegister(new(zone()) LLoadKeyed(obj, key));
   } else {
@@ -2256,9 +2256,10 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
   }
 
   bool needs_environment;
-  if (instr->is_fixed_typed_array()) {
+  if (instr->is_external() || instr->is_fixed_typed_array()) {
     // see LCodeGen::DoLoadKeyedExternalArray
-    needs_environment = elements_kind == UINT32_ELEMENTS &&
+    needs_environment = (elements_kind == EXTERNAL_UINT32_ELEMENTS ||
+                         elements_kind == UINT32_ELEMENTS) &&
                         !instr->CheckFlag(HInstruction::kUint32);
   } else {
     // see LCodeGen::DoLoadKeyedFixedDoubleArray and
@@ -2295,6 +2296,9 @@ LOperand* LChunkBuilder::GetStoreKeyedValueOperand(HStoreKeyed* instr) {
 
   // Determine if we need a byte register in this case for the value.
   bool val_is_fixed_register =
+      elements_kind == EXTERNAL_INT8_ELEMENTS ||
+      elements_kind == EXTERNAL_UINT8_ELEMENTS ||
+      elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS ||
       elements_kind == UINT8_ELEMENTS ||
       elements_kind == INT8_ELEMENTS ||
       elements_kind == UINT8_CLAMPED_ELEMENTS;
@@ -2307,7 +2311,7 @@ LOperand* LChunkBuilder::GetStoreKeyedValueOperand(HStoreKeyed* instr) {
 
 
 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
-  if (!instr->is_fixed_typed_array()) {
+  if (!instr->is_typed_elements()) {
     DCHECK(instr->elements()->representation().IsTagged());
     DCHECK(instr->key()->representation().IsInteger32() ||
            instr->key()->representation().IsSmi());
index 7a95ee4cd2bc7991b6e7221bbb804e2ead89af59..ac544a6af4d2e4706005622e1a234ac61639495d 100644 (file)
@@ -1641,9 +1641,15 @@ class LLoadKeyed final : public LTemplateInstruction<1, 2, 0> {
   ElementsKind elements_kind() const {
     return hydrogen()->elements_kind();
   }
+  bool is_external() const {
+    return hydrogen()->is_external();
+  }
   bool is_fixed_typed_array() const {
     return hydrogen()->is_fixed_typed_array();
   }
+  bool is_typed_elements() const {
+    return is_external() || is_fixed_typed_array();
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
   DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
@@ -1663,8 +1669,12 @@ inline static bool ExternalArrayOpRequiresTemp(
   // an index cannot fold the scale operation into a load and need an extra
   // temp register to do the work.
   return key_representation.IsSmi() &&
-         (elements_kind == UINT8_ELEMENTS || elements_kind == INT8_ELEMENTS ||
-          elements_kind == UINT8_CLAMPED_ELEMENTS);
+      (elements_kind == EXTERNAL_INT8_ELEMENTS ||
+       elements_kind == EXTERNAL_UINT8_ELEMENTS ||
+       elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS ||
+       elements_kind == UINT8_ELEMENTS ||
+       elements_kind == INT8_ELEMENTS ||
+       elements_kind == UINT8_CLAMPED_ELEMENTS);
 }
 
 
@@ -2249,9 +2259,13 @@ class LStoreKeyed final : public LTemplateInstruction<0, 3, 0> {
     inputs_[2] = val;
   }
 
+  bool is_external() const { return hydrogen()->is_external(); }
   bool is_fixed_typed_array() const {
     return hydrogen()->is_fixed_typed_array();
   }
+  bool is_typed_elements() const {
+    return is_external() || is_fixed_typed_array();
+  }
   LOperand* elements() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
   LOperand* value() { return inputs_[2]; }
index c7220afe1a4611e0a73b0d6b1cd97722f85b1f88..379e79fcac3bd0a0e55bb493fc18c775a9069e7a 100644 (file)
@@ -577,6 +577,7 @@ void ElementHandlerCompiler::CompileElementHandlers(
       } else if (IsSloppyArgumentsElements(elements_kind)) {
         cached_stub = KeyedLoadSloppyArgumentsStub(isolate()).GetCode();
       } else if (IsFastElementsKind(elements_kind) ||
+                 IsExternalArrayElementsKind(elements_kind) ||
                  IsFixedTypedArrayElementsKind(elements_kind)) {
         cached_stub = LoadFastElementStub(isolate(), is_js_array, elements_kind,
                                           convert_hole_to_undefined).GetCode();
index 4fe30234ee7bbe12759ad1e35f3cbd23f0a0c76c..a5ae6cfff4495e7bcd3d7e5b7050a6acdaa6c215 100644 (file)
@@ -109,6 +109,7 @@ Handle<Code> PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(
   } else if (receiver_map->has_sloppy_arguments_elements()) {
     stub = KeyedLoadSloppyArgumentsStub(isolate).GetCode();
   } else if (receiver_map->has_fast_elements() ||
+             receiver_map->has_external_array_elements() ||
              receiver_map->has_fixed_typed_array_elements()) {
     stub = LoadFastElementStub(isolate, is_js_array, elements_kind,
                                convert_hole_to_undefined).GetCode();
@@ -368,6 +369,7 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic(
       if (IsSloppyArgumentsElements(elements_kind)) {
         cached_stub = KeyedStoreSloppyArgumentsStub(isolate()).GetCode();
       } else if (receiver_map->has_fast_elements() ||
+                 receiver_map->has_external_array_elements() ||
                  receiver_map->has_fixed_typed_array_elements()) {
         cached_stub = StoreFastElementStub(isolate(), is_js_array,
                                            elements_kind, store_mode).GetCode();
@@ -399,6 +401,7 @@ Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphic(
   if (receiver_map->has_sloppy_arguments_elements()) {
     stub = KeyedStoreSloppyArgumentsStub(isolate()).GetCode();
   } else if (receiver_map->has_fast_elements() ||
+             receiver_map->has_external_array_elements() ||
              receiver_map->has_fixed_typed_array_elements()) {
     stub = StoreFastElementStub(isolate(), is_jsarray, elements_kind,
                                 store_mode).GetCode();
index 19f469982153a2268cb773fb953656b4b2d00a8c..99307f700d9f94cb92ac0dc9f2f13331ae9f010a 100644 (file)
@@ -1953,7 +1953,8 @@ Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver,
   if (store_mode != STANDARD_STORE) {
     int external_arrays = 0;
     for (int i = 0; i < target_receiver_maps.length(); ++i) {
-      if (target_receiver_maps[i]->has_fixed_typed_array_elements()) {
+      if (target_receiver_maps[i]->has_external_array_elements() ||
+          target_receiver_maps[i]->has_fixed_typed_array_elements()) {
         external_arrays++;
       }
     }
@@ -1990,7 +1991,7 @@ Handle<Map> KeyedStoreIC::ComputeTransitionedMap(
     case STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE:
       return Map::TransitionElementsTo(map, FAST_HOLEY_DOUBLE_ELEMENTS);
     case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS:
-      DCHECK(map->has_fixed_typed_array_elements());
+      DCHECK(map->has_external_array_elements());
     // Fall through
     case STORE_NO_TRANSITION_HANDLE_COW:
     case STANDARD_STORE:
@@ -2073,7 +2074,7 @@ static KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver,
       }
     }
     if (!FLAG_trace_external_array_abuse &&
-        receiver->map()->has_fixed_typed_array_elements() && oob_access) {
+        receiver->map()->has_external_array_elements() && oob_access) {
       return STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS;
     }
     Heap* heap = receiver->GetHeap();
index 75d460328daf13eba580f8db59ba47afd9780b0b..7d9f79168b8ec8969d83c03ef12ec040a817b13f 100644 (file)
@@ -117,7 +117,8 @@ void LookupIterator::ReloadPropertyInformation() {
 void LookupIterator::ReloadHolderMap() {
   DCHECK_EQ(DATA, state_);
   DCHECK(IsElement());
-  DCHECK(JSObject::cast(*holder_)->HasFixedTypedArrayElements());
+  DCHECK(JSObject::cast(*holder_)->HasExternalArrayElements() ||
+         JSObject::cast(*holder_)->HasFixedTypedArrayElements());
   if (*holder_map_ != holder_->map()) {
     holder_map_ = handle(holder_->map(), isolate_);
   }
@@ -160,6 +161,7 @@ void LookupIterator::ReconfigureDataProperty(Handle<Object> value,
   DCHECK(HolderIsReceiverOrHiddenPrototype());
   Handle<JSObject> holder = GetHolder<JSObject>();
   if (IsElement()) {
+    DCHECK(!holder->HasExternalArrayElements());
     DCHECK(!holder->HasFixedTypedArrayElements());
     DCHECK(attributes != NONE || !holder->HasFastElements());
     Handle<FixedArrayBase> elements(holder->elements());
index 43fa8be1cdeec090f2914b0598b7179b18f611a9..c5db715d6d0b7e08459405a41c38cdf4e2731a80 100644 (file)
@@ -3114,7 +3114,10 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
       ? (element_size_shift - kSmiTagSize) : element_size_shift;
   int base_offset = instr->base_offset();
 
-  if (elements_kind == FLOAT32_ELEMENTS || elements_kind == FLOAT64_ELEMENTS) {
+  if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+      elements_kind == FLOAT32_ELEMENTS ||
+      elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
+      elements_kind == FLOAT64_ELEMENTS) {
     FPURegister result = ToDoubleRegister(instr->result());
     if (key_is_constant) {
       __ Addu(scratch0(), external_pointer, constant_key << element_size_shift);
@@ -3122,7 +3125,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
       __ sll(scratch0(), key, shift_size);
       __ Addu(scratch0(), scratch0(), external_pointer);
     }
-    if (elements_kind == FLOAT32_ELEMENTS) {
+    if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+        elements_kind == FLOAT32_ELEMENTS) {
       __ lwc1(result, MemOperand(scratch0(), base_offset));
       __ cvt_d_s(result, result);
     } else  {  // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
@@ -3134,22 +3138,29 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
         key, external_pointer, key_is_constant, constant_key,
         element_size_shift, shift_size, base_offset);
     switch (elements_kind) {
+      case EXTERNAL_INT8_ELEMENTS:
       case INT8_ELEMENTS:
         __ lb(result, mem_operand);
         break;
+      case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
+      case EXTERNAL_UINT8_ELEMENTS:
       case UINT8_ELEMENTS:
       case UINT8_CLAMPED_ELEMENTS:
         __ lbu(result, mem_operand);
         break;
+      case EXTERNAL_INT16_ELEMENTS:
       case INT16_ELEMENTS:
         __ lh(result, mem_operand);
         break;
+      case EXTERNAL_UINT16_ELEMENTS:
       case UINT16_ELEMENTS:
         __ lhu(result, mem_operand);
         break;
+      case EXTERNAL_INT32_ELEMENTS:
       case INT32_ELEMENTS:
         __ lw(result, mem_operand);
         break;
+      case EXTERNAL_UINT32_ELEMENTS:
       case UINT32_ELEMENTS:
         __ lw(result, mem_operand);
         if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
@@ -3159,6 +3170,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
         break;
       case FLOAT32_ELEMENTS:
       case FLOAT64_ELEMENTS:
+      case EXTERNAL_FLOAT32_ELEMENTS:
+      case EXTERNAL_FLOAT64_ELEMENTS:
       case FAST_DOUBLE_ELEMENTS:
       case FAST_ELEMENTS:
       case FAST_SMI_ELEMENTS:
@@ -3270,7 +3283,7 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
 
 
 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
-  if (instr->is_fixed_typed_array()) {
+  if (instr->is_typed_elements()) {
     DoLoadKeyedExternalArray(instr);
   } else if (instr->hydrogen()->representation().IsDouble()) {
     DoLoadKeyedFixedDoubleArray(instr);
@@ -4265,7 +4278,10 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
       ? (element_size_shift - kSmiTagSize) : element_size_shift;
   int base_offset = instr->base_offset();
 
-  if (elements_kind == FLOAT32_ELEMENTS || elements_kind == FLOAT64_ELEMENTS) {
+  if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+      elements_kind == FLOAT32_ELEMENTS ||
+      elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
+      elements_kind == FLOAT64_ELEMENTS) {
     Register address = scratch0();
     FPURegister value(ToDoubleRegister(instr->value()));
     if (key_is_constant) {
@@ -4280,7 +4296,8 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
       __ Addu(address, external_pointer, address);
     }
 
-    if (elements_kind == FLOAT32_ELEMENTS) {
+    if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+        elements_kind == FLOAT32_ELEMENTS) {
       __ cvt_s_d(double_scratch0(), value);
       __ swc1(double_scratch0(), MemOperand(address, base_offset));
     } else {  // Storing doubles, not floats.
@@ -4293,21 +4310,30 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
         element_size_shift, shift_size,
         base_offset);
     switch (elements_kind) {
+      case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
+      case EXTERNAL_INT8_ELEMENTS:
+      case EXTERNAL_UINT8_ELEMENTS:
       case UINT8_ELEMENTS:
       case UINT8_CLAMPED_ELEMENTS:
       case INT8_ELEMENTS:
         __ sb(value, mem_operand);
         break;
+      case EXTERNAL_INT16_ELEMENTS:
+      case EXTERNAL_UINT16_ELEMENTS:
       case INT16_ELEMENTS:
       case UINT16_ELEMENTS:
         __ sh(value, mem_operand);
         break;
+      case EXTERNAL_INT32_ELEMENTS:
+      case EXTERNAL_UINT32_ELEMENTS:
       case INT32_ELEMENTS:
       case UINT32_ELEMENTS:
         __ sw(value, mem_operand);
         break;
       case FLOAT32_ELEMENTS:
       case FLOAT64_ELEMENTS:
+      case EXTERNAL_FLOAT32_ELEMENTS:
+      case EXTERNAL_FLOAT64_ELEMENTS:
       case FAST_DOUBLE_ELEMENTS:
       case FAST_ELEMENTS:
       case FAST_SMI_ELEMENTS:
@@ -4421,7 +4447,7 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
 
 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
   // By cases: external, fast double
-  if (instr->is_fixed_typed_array()) {
+  if (instr->is_typed_elements()) {
     DoStoreKeyedExternalArray(instr);
   } else if (instr->hydrogen()->value()->representation().IsDouble()) {
     DoStoreKeyedFixedDoubleArray(instr);
index 28e77e82c717b35c18668101c576506329637029..550610902f53bcbc9e838ce403f021b590993a18 100644 (file)
@@ -2187,7 +2187,7 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
   LOperand* key = UseRegisterOrConstantAtStart(instr->key());
   LInstruction* result = NULL;
 
-  if (!instr->is_fixed_typed_array()) {
+  if (!instr->is_typed_elements()) {
     LOperand* obj = NULL;
     if (instr->representation().IsDouble()) {
       obj = UseRegister(instr->elements());
@@ -2207,9 +2207,10 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
   }
 
   bool needs_environment;
-  if (instr->is_fixed_typed_array()) {
+  if (instr->is_external() || instr->is_fixed_typed_array()) {
     // see LCodeGen::DoLoadKeyedExternalArray
-    needs_environment = elements_kind == UINT32_ELEMENTS &&
+    needs_environment = (elements_kind == EXTERNAL_UINT32_ELEMENTS ||
+                         elements_kind == UINT32_ELEMENTS) &&
                         !instr->CheckFlag(HInstruction::kUint32);
   } else {
     // see LCodeGen::DoLoadKeyedFixedDoubleArray and
@@ -2244,7 +2245,7 @@ LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
 
 
 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
-  if (!instr->is_fixed_typed_array()) {
+  if (!instr->is_typed_elements()) {
     DCHECK(instr->elements()->representation().IsTagged());
     bool needs_write_barrier = instr->NeedsWriteBarrier();
     LOperand* object = NULL;
index e423b694b432ae0d9fb27f256db249a5c39db6df..1b8b5e5bfcfe107f1ecf4b635fbeb40904ce0fcc 100644 (file)
@@ -1610,9 +1610,15 @@ class LLoadKeyed final : public LTemplateInstruction<1, 2, 0> {
   ElementsKind elements_kind() const {
     return hydrogen()->elements_kind();
   }
+  bool is_external() const {
+    return hydrogen()->is_external();
+  }
   bool is_fixed_typed_array() const {
     return hydrogen()->is_fixed_typed_array();
   }
+  bool is_typed_elements() const {
+    return is_external() || is_fixed_typed_array();
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
   DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
@@ -2212,9 +2218,13 @@ class LStoreKeyed final : public LTemplateInstruction<0, 3, 0> {
     inputs_[2] = value;
   }
 
+  bool is_external() const { return hydrogen()->is_external(); }
   bool is_fixed_typed_array() const {
     return hydrogen()->is_fixed_typed_array();
   }
+  bool is_typed_elements() const {
+    return is_external() || is_fixed_typed_array();
+  }
   LOperand* elements() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
   LOperand* value() { return inputs_[2]; }
index a13937c2f728e44039a7140485fc37fc96d07cde..0313878b2e573e693dc62256c70cfc1b187758d6 100644 (file)
@@ -3234,7 +3234,10 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
       : element_size_shift;
   int base_offset = instr->base_offset();
 
-  if (elements_kind == FLOAT32_ELEMENTS || elements_kind == FLOAT64_ELEMENTS) {
+  if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+      elements_kind == FLOAT32_ELEMENTS ||
+      elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
+      elements_kind == FLOAT64_ELEMENTS) {
     FPURegister result = ToDoubleRegister(instr->result());
     if (key_is_constant) {
       __ Daddu(scratch0(), external_pointer,
@@ -3251,7 +3254,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
       }
       __ Daddu(scratch0(), scratch0(), external_pointer);
     }
-    if (elements_kind == FLOAT32_ELEMENTS) {
+    if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+        elements_kind == FLOAT32_ELEMENTS) {
       __ lwc1(result, MemOperand(scratch0(), base_offset));
       __ cvt_d_s(result, result);
     } else  {  // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
@@ -3263,22 +3267,29 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
         key, external_pointer, key_is_constant, constant_key,
         element_size_shift, shift_size, base_offset);
     switch (elements_kind) {
+      case EXTERNAL_INT8_ELEMENTS:
       case INT8_ELEMENTS:
         __ lb(result, mem_operand);
         break;
+      case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
+      case EXTERNAL_UINT8_ELEMENTS:
       case UINT8_ELEMENTS:
       case UINT8_CLAMPED_ELEMENTS:
         __ lbu(result, mem_operand);
         break;
+      case EXTERNAL_INT16_ELEMENTS:
       case INT16_ELEMENTS:
         __ lh(result, mem_operand);
         break;
+      case EXTERNAL_UINT16_ELEMENTS:
       case UINT16_ELEMENTS:
         __ lhu(result, mem_operand);
         break;
+      case EXTERNAL_INT32_ELEMENTS:
       case INT32_ELEMENTS:
         __ lw(result, mem_operand);
         break;
+      case EXTERNAL_UINT32_ELEMENTS:
       case UINT32_ELEMENTS:
         __ lw(result, mem_operand);
         if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
@@ -3288,6 +3299,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
         break;
       case FLOAT32_ELEMENTS:
       case FLOAT64_ELEMENTS:
+      case EXTERNAL_FLOAT32_ELEMENTS:
+      case EXTERNAL_FLOAT64_ELEMENTS:
       case FAST_DOUBLE_ELEMENTS:
       case FAST_ELEMENTS:
       case FAST_SMI_ELEMENTS:
@@ -3425,7 +3438,7 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
 
 
 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
-  if (instr->is_fixed_typed_array()) {
+  if (instr->is_typed_elements()) {
     DoLoadKeyedExternalArray(instr);
   } else if (instr->hydrogen()->representation().IsDouble()) {
     DoLoadKeyedFixedDoubleArray(instr);
@@ -4459,7 +4472,10 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
       : element_size_shift;
   int base_offset = instr->base_offset();
 
-  if (elements_kind == FLOAT32_ELEMENTS || elements_kind == FLOAT64_ELEMENTS) {
+  if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+      elements_kind == FLOAT32_ELEMENTS ||
+      elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
+      elements_kind == FLOAT64_ELEMENTS) {
     Register address = scratch0();
     FPURegister value(ToDoubleRegister(instr->value()));
     if (key_is_constant) {
@@ -4482,7 +4498,8 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
       __ Daddu(address, external_pointer, address);
     }
 
-    if (elements_kind == FLOAT32_ELEMENTS) {
+    if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+        elements_kind == FLOAT32_ELEMENTS) {
       __ cvt_s_d(double_scratch0(), value);
       __ swc1(double_scratch0(), MemOperand(address, base_offset));
     } else {  // Storing doubles, not floats.
@@ -4495,21 +4512,30 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
         element_size_shift, shift_size,
         base_offset);
     switch (elements_kind) {
+      case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
+      case EXTERNAL_INT8_ELEMENTS:
+      case EXTERNAL_UINT8_ELEMENTS:
       case UINT8_ELEMENTS:
       case UINT8_CLAMPED_ELEMENTS:
       case INT8_ELEMENTS:
         __ sb(value, mem_operand);
         break;
+      case EXTERNAL_INT16_ELEMENTS:
+      case EXTERNAL_UINT16_ELEMENTS:
       case INT16_ELEMENTS:
       case UINT16_ELEMENTS:
         __ sh(value, mem_operand);
         break;
+      case EXTERNAL_INT32_ELEMENTS:
+      case EXTERNAL_UINT32_ELEMENTS:
       case INT32_ELEMENTS:
       case UINT32_ELEMENTS:
         __ sw(value, mem_operand);
         break;
       case FLOAT32_ELEMENTS:
       case FLOAT64_ELEMENTS:
+      case EXTERNAL_FLOAT32_ELEMENTS:
+      case EXTERNAL_FLOAT64_ELEMENTS:
       case FAST_DOUBLE_ELEMENTS:
       case FAST_ELEMENTS:
       case FAST_SMI_ELEMENTS:
@@ -4636,7 +4662,7 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
 
 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
   // By cases: external, fast double
-  if (instr->is_fixed_typed_array()) {
+  if (instr->is_typed_elements()) {
     DoStoreKeyedExternalArray(instr);
   } else if (instr->hydrogen()->value()->representation().IsDouble()) {
     DoStoreKeyedFixedDoubleArray(instr);
index 6a30a446d570ad47420057f66ee0a1c98394d0f7..060582585d744e953f32c7cdcdd0e396a33e87bb 100644 (file)
@@ -2190,7 +2190,7 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
   LOperand* key = UseRegisterOrConstantAtStart(instr->key());
   LInstruction* result = NULL;
 
-  if (!instr->is_fixed_typed_array()) {
+  if (!instr->is_typed_elements()) {
     LOperand* obj = NULL;
     if (instr->representation().IsDouble()) {
       obj = UseRegister(instr->elements());
@@ -2211,9 +2211,10 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
   }
 
   bool needs_environment;
-  if (instr->is_fixed_typed_array()) {
+  if (instr->is_external() || instr->is_fixed_typed_array()) {
     // see LCodeGen::DoLoadKeyedExternalArray
-    needs_environment = elements_kind == UINT32_ELEMENTS &&
+    needs_environment = (elements_kind == EXTERNAL_UINT32_ELEMENTS ||
+                         elements_kind == UINT32_ELEMENTS) &&
                         !instr->CheckFlag(HInstruction::kUint32);
   } else {
     // see LCodeGen::DoLoadKeyedFixedDoubleArray and
@@ -2248,7 +2249,7 @@ LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
 
 
 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
-  if (!instr->is_fixed_typed_array()) {
+  if (!instr->is_typed_elements()) {
     DCHECK(instr->elements()->representation().IsTagged());
     bool needs_write_barrier = instr->NeedsWriteBarrier();
     LOperand* object = NULL;
index 9a8681f069604523bb9340da400de9ca07e852f0..24088699d2a68436be29e6b3a59be85152c8201e 100644 (file)
@@ -1672,9 +1672,15 @@ class LLoadKeyed final : public LTemplateInstruction<1, 2, 0> {
   ElementsKind elements_kind() const {
     return hydrogen()->elements_kind();
   }
+  bool is_external() const {
+    return hydrogen()->is_external();
+  }
   bool is_fixed_typed_array() const {
     return hydrogen()->is_fixed_typed_array();
   }
+  bool is_typed_elements() const {
+    return is_external() || is_fixed_typed_array();
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
   DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
@@ -2258,9 +2264,13 @@ class LStoreKeyed final : public LTemplateInstruction<0, 3, 0> {
     inputs_[2] = value;
   }
 
+  bool is_external() const { return hydrogen()->is_external(); }
   bool is_fixed_typed_array() const {
     return hydrogen()->is_fixed_typed_array();
   }
+  bool is_typed_elements() const {
+    return is_external() || is_fixed_typed_array();
+  }
   LOperand* elements() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
   LOperand* value() { return inputs_[2]; }
index 5babfdf1a7f434ce341a735b9daf1f9ee61813a5..b68895fbc6d27745e4dd8e1ca6bc71674b772ef9 100644 (file)
@@ -78,6 +78,9 @@ void HeapObject::HeapObjectVerify() {
       break;
 
 #define VERIFY_TYPED_ARRAY(Type, type, TYPE, ctype, size)                      \
+    case EXTERNAL_##TYPE##_ARRAY_TYPE:                                         \
+      External##Type##Array::cast(this)->External##Type##ArrayVerify();        \
+      break;                                                                   \
     case FIXED_##TYPE##_ARRAY_TYPE:                                            \
       Fixed##Type##Array::cast(this)->FixedTypedArrayVerify();                 \
       break;
@@ -233,17 +236,21 @@ void FreeSpace::FreeSpaceVerify() {
 }
 
 
+#define EXTERNAL_ARRAY_VERIFY(Type, type, TYPE, ctype, size)                  \
+  void External##Type##Array::External##Type##ArrayVerify() {                 \
+    CHECK(IsExternal##Type##Array());                                         \
+  }
+
+TYPED_ARRAYS(EXTERNAL_ARRAY_VERIFY)
+#undef EXTERNAL_ARRAY_VERIFY
+
+
 template <class Traits>
 void FixedTypedArray<Traits>::FixedTypedArrayVerify() {
   CHECK(IsHeapObject() &&
         HeapObject::cast(this)->map()->instance_type() ==
             Traits::kInstanceType);
-  if (base_pointer() == this) {
-    CHECK(external_pointer() ==
-          ExternalReference::fixed_typed_array_base_data_offset().address());
-  } else {
-    CHECK(base_pointer() == nullptr);
-  }
+  CHECK(base_pointer() == this);
 }
 
 
@@ -1089,6 +1096,7 @@ void JSObject::IncrementSpillStatistics(SpillInformation* info) {
     }
 
 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
+    case EXTERNAL_##TYPE##_ELEMENTS:                                          \
     case TYPE##_ELEMENTS:
 
     TYPED_ARRAYS(TYPED_ARRAY_CASE)
index 4929c0d2dfd56a70900d070e8d2b2e87f52120c2..8e28aacd7bd18ecbdc48c112162a790efe030639 100644 (file)
@@ -141,7 +141,8 @@ int PropertyDetails::field_width_in_words() const {
 
 
 bool Object::IsFixedArrayBase() const {
-  return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase();
+  return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase() ||
+         IsExternalArray();
 }
 
 
@@ -269,7 +270,8 @@ bool Object::IsExternalTwoByteString() const {
 
 bool Object::HasValidElements() {
   // Dictionary is covered under FixedArray.
-  return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase();
+  return IsFixedArray() || IsFixedDoubleArray() || IsExternalArray() ||
+         IsFixedTypedArrayBase();
 }
 
 
@@ -657,8 +659,18 @@ bool Object::IsFiller() const {
 }
 
 
+bool Object::IsExternalArray() const {
+  if (!Object::IsHeapObject())
+    return false;
+  InstanceType instance_type =
+      HeapObject::cast(this)->map()->instance_type();
+  return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
+          instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
+}
+
 
 #define TYPED_ARRAY_TYPE_CHECKER(Type, type, TYPE, ctype, size)               \
+  TYPE_CHECKER(External##Type##Array, EXTERNAL_##TYPE##_ARRAY_TYPE)           \
   TYPE_CHECKER(Fixed##Type##Array, FIXED_##TYPE##_ARRAY_TYPE)
 
 TYPED_ARRAYS(TYPED_ARRAY_TYPE_CHECKER)
@@ -2631,6 +2643,10 @@ FixedArrayBase* Map::GetInitialElements() {
       has_fast_double_elements()) {
     DCHECK(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
     return GetHeap()->empty_fixed_array();
+  } else if (has_external_array_elements()) {
+    ExternalArray* empty_array = GetHeap()->EmptyExternalArrayForMap(this);
+    DCHECK(!GetHeap()->InNewSpace(empty_array));
+    return empty_array;
   } else if (has_fixed_typed_array_elements()) {
     FixedTypedArrayBase* empty_array =
         GetHeap()->EmptyFixedTypedArrayForMap(this);
@@ -2919,9 +2935,19 @@ CAST_ACCESSOR(DeoptimizationInputData)
 CAST_ACCESSOR(DeoptimizationOutputData)
 CAST_ACCESSOR(DependentCode)
 CAST_ACCESSOR(DescriptorArray)
+CAST_ACCESSOR(ExternalArray)
 CAST_ACCESSOR(ExternalOneByteString)
+CAST_ACCESSOR(ExternalFloat32Array)
+CAST_ACCESSOR(ExternalFloat64Array)
+CAST_ACCESSOR(ExternalInt16Array)
+CAST_ACCESSOR(ExternalInt32Array)
+CAST_ACCESSOR(ExternalInt8Array)
 CAST_ACCESSOR(ExternalString)
 CAST_ACCESSOR(ExternalTwoByteString)
+CAST_ACCESSOR(ExternalUint16Array)
+CAST_ACCESSOR(ExternalUint32Array)
+CAST_ACCESSOR(ExternalUint8Array)
+CAST_ACCESSOR(ExternalUint8ClampedArray)
 CAST_ACCESSOR(FixedArray)
 CAST_ACCESSOR(FixedArrayBase)
 CAST_ACCESSOR(FixedDoubleArray)
@@ -3631,6 +3657,211 @@ Address BytecodeArray::GetFirstBytecodeAddress() {
 }
 
 
+uint8_t* ExternalUint8ClampedArray::external_uint8_clamped_pointer() {
+  return reinterpret_cast<uint8_t*>(external_pointer());
+}
+
+
+uint8_t ExternalUint8ClampedArray::get_scalar(int index) {
+  DCHECK((index >= 0) && (index < this->length()));
+  uint8_t* ptr = external_uint8_clamped_pointer();
+  return ptr[index];
+}
+
+
+Handle<Object> ExternalUint8ClampedArray::get(
+    Handle<ExternalUint8ClampedArray> array,
+    int index) {
+  return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
+                     array->GetIsolate());
+}
+
+
+void ExternalUint8ClampedArray::set(int index, uint8_t value) {
+  DCHECK((index >= 0) && (index < this->length()));
+  uint8_t* ptr = external_uint8_clamped_pointer();
+  ptr[index] = value;
+}
+
+
+void* ExternalArray::external_pointer() const {
+  intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
+  return reinterpret_cast<void*>(ptr);
+}
+
+
+void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
+  intptr_t ptr = reinterpret_cast<intptr_t>(value);
+  WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
+}
+
+
+int8_t ExternalInt8Array::get_scalar(int index) {
+  DCHECK((index >= 0) && (index < this->length()));
+  int8_t* ptr = static_cast<int8_t*>(external_pointer());
+  return ptr[index];
+}
+
+
+Handle<Object> ExternalInt8Array::get(Handle<ExternalInt8Array> array,
+                                      int index) {
+  return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
+                     array->GetIsolate());
+}
+
+
+void ExternalInt8Array::set(int index, int8_t value) {
+  DCHECK((index >= 0) && (index < this->length()));
+  int8_t* ptr = static_cast<int8_t*>(external_pointer());
+  ptr[index] = value;
+}
+
+
+uint8_t ExternalUint8Array::get_scalar(int index) {
+  DCHECK((index >= 0) && (index < this->length()));
+  uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
+  return ptr[index];
+}
+
+
+Handle<Object> ExternalUint8Array::get(Handle<ExternalUint8Array> array,
+                                       int index) {
+  return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
+                     array->GetIsolate());
+}
+
+
+void ExternalUint8Array::set(int index, uint8_t value) {
+  DCHECK((index >= 0) && (index < this->length()));
+  uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
+  ptr[index] = value;
+}
+
+
+int16_t ExternalInt16Array::get_scalar(int index) {
+  DCHECK((index >= 0) && (index < this->length()));
+  int16_t* ptr = static_cast<int16_t*>(external_pointer());
+  return ptr[index];
+}
+
+
+Handle<Object> ExternalInt16Array::get(Handle<ExternalInt16Array> array,
+                                       int index) {
+  return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
+                     array->GetIsolate());
+}
+
+
+void ExternalInt16Array::set(int index, int16_t value) {
+  DCHECK((index >= 0) && (index < this->length()));
+  int16_t* ptr = static_cast<int16_t*>(external_pointer());
+  ptr[index] = value;
+}
+
+
+uint16_t ExternalUint16Array::get_scalar(int index) {
+  DCHECK((index >= 0) && (index < this->length()));
+  uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
+  return ptr[index];
+}
+
+
+Handle<Object> ExternalUint16Array::get(Handle<ExternalUint16Array> array,
+                                        int index) {
+  return Handle<Smi>(Smi::FromInt(array->get_scalar(index)),
+                     array->GetIsolate());
+}
+
+
+void ExternalUint16Array::set(int index, uint16_t value) {
+  DCHECK((index >= 0) && (index < this->length()));
+  uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
+  ptr[index] = value;
+}
+
+
+int32_t ExternalInt32Array::get_scalar(int index) {
+  DCHECK((index >= 0) && (index < this->length()));
+  int32_t* ptr = static_cast<int32_t*>(external_pointer());
+  return ptr[index];
+}
+
+
+Handle<Object> ExternalInt32Array::get(Handle<ExternalInt32Array> array,
+                                       int index) {
+  return array->GetIsolate()->factory()->
+      NewNumberFromInt(array->get_scalar(index));
+}
+
+
+void ExternalInt32Array::set(int index, int32_t value) {
+  DCHECK((index >= 0) && (index < this->length()));
+  int32_t* ptr = static_cast<int32_t*>(external_pointer());
+  ptr[index] = value;
+}
+
+
+uint32_t ExternalUint32Array::get_scalar(int index) {
+  DCHECK((index >= 0) && (index < this->length()));
+  uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
+  return ptr[index];
+}
+
+
+Handle<Object> ExternalUint32Array::get(Handle<ExternalUint32Array> array,
+                                        int index) {
+  return array->GetIsolate()->factory()->
+      NewNumberFromUint(array->get_scalar(index));
+}
+
+
+void ExternalUint32Array::set(int index, uint32_t value) {
+  DCHECK((index >= 0) && (index < this->length()));
+  uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
+  ptr[index] = value;
+}
+
+
+float ExternalFloat32Array::get_scalar(int index) {
+  DCHECK((index >= 0) && (index < this->length()));
+  float* ptr = static_cast<float*>(external_pointer());
+  return ptr[index];
+}
+
+
+Handle<Object> ExternalFloat32Array::get(Handle<ExternalFloat32Array> array,
+                                         int index) {
+  return array->GetIsolate()->factory()->NewNumber(array->get_scalar(index));
+}
+
+
+void ExternalFloat32Array::set(int index, float value) {
+  DCHECK((index >= 0) && (index < this->length()));
+  float* ptr = static_cast<float*>(external_pointer());
+  ptr[index] = value;
+}
+
+
+double ExternalFloat64Array::get_scalar(int index) {
+  DCHECK((index >= 0) && (index < this->length()));
+  double* ptr = static_cast<double*>(external_pointer());
+  return ptr[index];
+}
+
+
+Handle<Object> ExternalFloat64Array::get(Handle<ExternalFloat64Array> array,
+                                         int index) {
+  return array->GetIsolate()->factory()->NewNumber(array->get_scalar(index));
+}
+
+
+void ExternalFloat64Array::set(int index, double value) {
+  DCHECK((index >= 0) && (index < this->length()));
+  double* ptr = static_cast<double*>(external_pointer());
+  ptr[index] = value;
+}
+
+
 ACCESSORS(FixedTypedArrayBase, base_pointer, Object, kBasePointerOffset)
 
 
@@ -3673,7 +3904,6 @@ int FixedTypedArrayBase::ElementSize(InstanceType type) {
 
 
 int FixedTypedArrayBase::DataSize(InstanceType type) {
-  if (base_pointer() == Smi::FromInt(0)) return 0;
   return length() * ElementSize(type);
 }
 
@@ -6081,6 +6311,27 @@ bool JSObject::HasSloppyArgumentsElements() {
 }
 
 
+bool JSObject::HasExternalArrayElements() {
+  HeapObject* array = elements();
+  DCHECK(array != NULL);
+  return array->IsExternalArray();
+}
+
+
+#define EXTERNAL_ELEMENTS_CHECK(Type, type, TYPE, ctype, size)          \
+bool JSObject::HasExternal##Type##Elements() {                          \
+  HeapObject* array = elements();                                       \
+  DCHECK(array != NULL);                                                \
+  if (!array->IsHeapObject())                                           \
+    return false;                                                       \
+  return array->map()->instance_type() == EXTERNAL_##TYPE##_ARRAY_TYPE; \
+}
+
+TYPED_ARRAYS(EXTERNAL_ELEMENTS_CHECK)
+
+#undef EXTERNAL_ELEMENTS_CHECK
+
+
 bool JSObject::HasFixedTypedArrayElements() {
   HeapObject* array = elements();
   DCHECK(array != NULL);
@@ -6752,7 +7003,7 @@ bool JSArray::SetLengthWouldNormalize(Heap* heap, uint32_t new_length) {
 
 bool JSArray::AllowsSetLength() {
   bool result = elements()->IsFixedArray() || elements()->IsFixedDoubleArray();
-  DCHECK(result == !HasFixedTypedArrayElements());
+  DCHECK(result == !HasExternalArrayElements());
   return result;
 }
 
index cb67d6a6e86a60d058af4cd21fae5ec163607086..f45a035451f63f2b16af25a748abb4d5bec9bac4 100644 (file)
@@ -80,6 +80,14 @@ void HeapObject::HeapObjectPrint(std::ostream& os) {  // NOLINT
       FreeSpace::cast(this)->FreeSpacePrint(os);
       break;
 
+#define PRINT_EXTERNAL_ARRAY(Type, type, TYPE, ctype, size)            \
+  case EXTERNAL_##TYPE##_ARRAY_TYPE:                                   \
+    External##Type##Array::cast(this)->External##Type##ArrayPrint(os); \
+    break;
+
+     TYPED_ARRAYS(PRINT_EXTERNAL_ARRAY)
+#undef PRINT_EXTERNAL_ARRAY
+
 #define PRINT_FIXED_TYPED_ARRAY(Type, type, TYPE, ctype, size) \
   case Fixed##Type##Array::kInstanceType:                      \
     Fixed##Type##Array::cast(this)->FixedTypedArrayPrint(os);  \
@@ -207,6 +215,16 @@ void FreeSpace::FreeSpacePrint(std::ostream& os) {  // NOLINT
 }
 
 
+#define EXTERNAL_ARRAY_PRINTER(Type, type, TYPE, ctype, size)                \
+  void External##Type##Array::External##Type##ArrayPrint(std::ostream& os) { \
+    os << "external " #type " array";                                        \
+  }
+
+TYPED_ARRAYS(EXTERNAL_ARRAY_PRINTER)
+
+#undef EXTERNAL_ARRAY_PRINTER
+
+
 template <class Traits>
 void FixedTypedArray<Traits>::FixedTypedArrayPrint(
     std::ostream& os) {  // NOLINT
@@ -303,6 +321,19 @@ void JSObject::PrintElements(std::ostream& os) {  // NOLINT
     break;                                 \
   }
 
+    PRINT_ELEMENTS(EXTERNAL_UINT8_CLAMPED_ELEMENTS, ExternalUint8ClampedArray)
+    PRINT_ELEMENTS(EXTERNAL_INT8_ELEMENTS, ExternalInt8Array)
+    PRINT_ELEMENTS(EXTERNAL_UINT8_ELEMENTS,
+        ExternalUint8Array)
+    PRINT_ELEMENTS(EXTERNAL_INT16_ELEMENTS, ExternalInt16Array)
+    PRINT_ELEMENTS(EXTERNAL_UINT16_ELEMENTS,
+        ExternalUint16Array)
+    PRINT_ELEMENTS(EXTERNAL_INT32_ELEMENTS, ExternalInt32Array)
+    PRINT_ELEMENTS(EXTERNAL_UINT32_ELEMENTS,
+        ExternalUint32Array)
+    PRINT_ELEMENTS(EXTERNAL_FLOAT32_ELEMENTS, ExternalFloat32Array)
+    PRINT_ELEMENTS(EXTERNAL_FLOAT64_ELEMENTS, ExternalFloat64Array)
+
     PRINT_ELEMENTS(UINT8_ELEMENTS, FixedUint8Array)
     PRINT_ELEMENTS(UINT8_CLAMPED_ELEMENTS, FixedUint8ClampedArray)
     PRINT_ELEMENTS(INT8_ELEMENTS, FixedInt8Array)
index c6d613b2cdba323590c1fce1c367bafc19712360..2e1443ab47ed246fd65e657905f35b21568169ba 100644 (file)
@@ -1281,6 +1281,10 @@ void HeapObject::HeapObjectShortPrint(std::ostream& os) {  // NOLINT
       os << "<FreeSpace[" << FreeSpace::cast(this)->Size() << "]>";
       break;
 #define TYPED_ARRAY_SHORT_PRINT(Type, type, TYPE, ctype, size)                \
+  case EXTERNAL_##TYPE##_ARRAY_TYPE:                                          \
+    os << "<External" #Type "Array["                                          \
+       << External##Type##Array::cast(this)->length() << "]>";                \
+    break;                                                                    \
   case FIXED_##TYPE##_ARRAY_TYPE:                                             \
     os << "<Fixed" #Type "Array[" << Fixed##Type##Array::cast(this)->length() \
        << "]>";                                                               \
@@ -1504,6 +1508,9 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
       break;
 
 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
+  case EXTERNAL_##TYPE##_ARRAY_TYPE:                    \
+    break;                                              \
+                                                        \
   case FIXED_##TYPE##_ARRAY_TYPE:                       \
     reinterpret_cast<FixedTypedArrayBase*>(this)        \
         ->FixedTypedArrayBaseIterateBody(v);            \
@@ -3311,7 +3318,8 @@ MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it,
 
   Handle<Object> to_assign = value;
   // Convert the incoming value to a number for storing into typed arrays.
-  if (it->IsElement() && receiver->HasFixedTypedArrayElements()) {
+  if (it->IsElement() && (receiver->HasExternalArrayElements() ||
+                          receiver->HasFixedTypedArrayElements())) {
     if (!value->IsNumber() && !value->IsUndefined()) {
       ASSIGN_RETURN_ON_EXCEPTION(it->isolate(), to_assign,
                                  Execution::ToNumber(it->isolate(), value),
@@ -3423,11 +3431,13 @@ MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it,
       }
 
       if (FLAG_trace_external_array_abuse &&
-          array->HasFixedTypedArrayElements()) {
+          (array->HasExternalArrayElements() ||
+           array->HasFixedTypedArrayElements())) {
         CheckArrayAbuse(array, "typed elements write", it->index(), true);
       }
 
-      if (FLAG_trace_js_array_abuse && !array->HasFixedTypedArrayElements()) {
+      if (FLAG_trace_js_array_abuse && !array->HasExternalArrayElements() &&
+          !array->HasFixedTypedArrayElements()) {
         CheckArrayAbuse(array, "elements write", it->index(), false);
       }
     }
@@ -4256,7 +4266,8 @@ MaybeHandle<Object> JSObject::DefineOwnPropertyIgnoreAttributes(
 
         // Special case: properties of typed arrays cannot be reconfigured to
         // non-writable nor to non-enumerable.
-        if (it->IsElement() && object->HasFixedTypedArrayElements()) {
+        if (it->IsElement() && (object->HasExternalArrayElements() ||
+                                object->HasFixedTypedArrayElements())) {
           return RedefineNonconfigurableProperty(it->isolate(), it->GetName(),
                                                  value, STRICT);
         }
@@ -4839,7 +4850,8 @@ Handle<SeededNumberDictionary> JSObject::GetNormalizedElementDictionary(
 
 Handle<SeededNumberDictionary> JSObject::NormalizeElements(
     Handle<JSObject> object) {
-  DCHECK(!object->HasFixedTypedArrayElements());
+  DCHECK(!object->HasExternalArrayElements() &&
+         !object->HasFixedTypedArrayElements());
   Isolate* isolate = object->GetIsolate();
 
   // Find the backing store.
@@ -5344,6 +5356,7 @@ bool JSObject::ReferencesObject(Object* obj) {
     // Raw pixels and external arrays do not reference other
     // objects.
 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
+    case EXTERNAL_##TYPE##_ELEMENTS:                                           \
     case TYPE##_ELEMENTS:                                                      \
       break;
 
@@ -5453,7 +5466,8 @@ MaybeHandle<Object> JSObject::PreventExtensions(Handle<JSObject> object) {
   }
 
   // It's not possible to seal objects with external array elements
-  if (object->HasFixedTypedArrayElements()) {
+  if (object->HasExternalArrayElements() ||
+      object->HasFixedTypedArrayElements()) {
     THROW_NEW_ERROR(
         isolate, NewTypeError(MessageTemplate::kCannotPreventExtExternalArray),
         Object);
@@ -5546,7 +5560,8 @@ MaybeHandle<Object> JSObject::PreventExtensionsWithTransition(
   }
 
   // It's not possible to seal or freeze objects with external array elements
-  if (object->HasFixedTypedArrayElements()) {
+  if (object->HasExternalArrayElements() ||
+      object->HasFixedTypedArrayElements()) {
     THROW_NEW_ERROR(
         isolate, NewTypeError(MessageTemplate::kCannotPreventExtExternalArray),
         Object);
@@ -5815,7 +5830,7 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
 
     // Deep copy own elements.
     // Pixel elements cannot be created using an object literal.
-    DCHECK(!copy->HasFixedTypedArrayElements());
+    DCHECK(!copy->HasExternalArrayElements());
     switch (kind) {
       case FAST_SMI_ELEMENTS:
       case FAST_ELEMENTS:
@@ -5877,6 +5892,7 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
 
 
 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
+      case EXTERNAL_##TYPE##_ELEMENTS:                                         \
       case TYPE##_ELEMENTS:                                                    \
 
       TYPED_ARRAYS(TYPED_ARRAY_CASE)
@@ -6279,7 +6295,8 @@ MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object,
   }
 
   // Ignore accessors on typed arrays.
-  if (it.IsElement() && object->HasFixedTypedArrayElements()) {
+  if (it.IsElement() && (object->HasFixedTypedArrayElements() ||
+                         object->HasExternalArrayElements())) {
     return it.factory()->undefined_value();
   }
 
@@ -6342,7 +6359,8 @@ MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object,
   }
 
   // Ignore accessors on typed arrays.
-  if (it.IsElement() && object->HasFixedTypedArrayElements()) {
+  if (it.IsElement() && (object->HasFixedTypedArrayElements() ||
+                         object->HasExternalArrayElements())) {
     return it.factory()->undefined_value();
   }
 
@@ -6759,10 +6777,13 @@ Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind,
   Map* maybe_elements_transition_map = NULL;
   if (flag == INSERT_TRANSITION) {
     maybe_elements_transition_map = map->ElementsTransitionMap();
-    DCHECK(maybe_elements_transition_map == NULL ||
-           (maybe_elements_transition_map->elements_kind() ==
-                DICTIONARY_ELEMENTS &&
-            kind == DICTIONARY_ELEMENTS));
+    DCHECK(
+        maybe_elements_transition_map == NULL ||
+        ((maybe_elements_transition_map->elements_kind() ==
+              DICTIONARY_ELEMENTS ||
+          IsExternalArrayElementsKind(
+              maybe_elements_transition_map->elements_kind())) &&
+         (kind == DICTIONARY_ELEMENTS || IsExternalArrayElementsKind(kind))));
     DCHECK(!IsFastElementsKind(kind) ||
            IsMoreGeneralElementsKindTransition(map->elements_kind(), kind));
     DCHECK(kind != map->elements_kind());
@@ -12578,6 +12599,7 @@ int JSObject::GetFastElementsUsage() {
     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
     case DICTIONARY_ELEMENTS:
 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
+    case EXTERNAL_##TYPE##_ELEMENTS:                                         \
     case TYPE##_ELEMENTS:                                                    \
 
     TYPED_ARRAYS(TYPED_ARRAY_CASE)
@@ -13011,6 +13033,7 @@ int JSObject::GetOwnElementKeys(FixedArray* storage,
     }
 
 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
+    case EXTERNAL_##TYPE##_ELEMENTS:                                         \
     case TYPE##_ELEMENTS:                                                    \
 
     TYPED_ARRAYS(TYPED_ARRAY_CASE)
@@ -13832,7 +13855,8 @@ Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object,
     JSObject::ValidateElements(object);
 
     JSObject::SetMapAndElements(object, new_map, fast_elements);
-  } else if (object->HasFixedTypedArrayElements()) {
+  } else if (object->HasExternalArrayElements() ||
+             object->HasFixedTypedArrayElements()) {
     // Typed arrays cannot have holes or undefined elements.
     return handle(Smi::FromInt(
         FixedArrayBase::cast(object->elements())->length()), isolate);
@@ -13935,6 +13959,7 @@ Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object,
 ExternalArrayType JSTypedArray::type() {
   switch (elements()->map()->instance_type()) {
 #define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size)            \
+    case EXTERNAL_##TYPE##_ARRAY_TYPE:                                        \
     case FIXED_##TYPE##_ARRAY_TYPE:                                           \
       return kExternal##Type##Array;
 
@@ -13950,9 +13975,9 @@ ExternalArrayType JSTypedArray::type() {
 
 size_t JSTypedArray::element_size() {
   switch (elements()->map()->instance_type()) {
-#define INSTANCE_TYPE_TO_ELEMENT_SIZE(Type, type, TYPE, ctype, size) \
-  case FIXED_##TYPE##_ARRAY_TYPE:                                    \
-    return size;
+#define INSTANCE_TYPE_TO_ELEMENT_SIZE(Type, type, TYPE, ctype, size)          \
+    case EXTERNAL_##TYPE##_ARRAY_TYPE:                                        \
+      return size;
 
     TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENT_SIZE)
 #undef INSTANCE_TYPE_TO_ELEMENT_SIZE
@@ -13970,6 +13995,131 @@ void FixedArray::SetValue(uint32_t index, Object* value) { set(index, value); }
 void FixedDoubleArray::SetValue(uint32_t index, Object* value) {
   set(index, value->Number());
 }
+
+
+void ExternalUint8ClampedArray::SetValue(uint32_t index, Object* value) {
+  uint8_t clamped_value = 0;
+  if (value->IsSmi()) {
+    int int_value = Smi::cast(value)->value();
+    if (int_value < 0) {
+      clamped_value = 0;
+    } else if (int_value > 255) {
+      clamped_value = 255;
+    } else {
+      clamped_value = static_cast<uint8_t>(int_value);
+    }
+  } else if (value->IsHeapNumber()) {
+    double double_value = HeapNumber::cast(value)->value();
+    if (!(double_value > 0)) {
+      // NaN and less than zero clamp to zero.
+      clamped_value = 0;
+    } else if (double_value > 255) {
+      // Greater than 255 clamp to 255.
+      clamped_value = 255;
+    } else {
+      // Other doubles are rounded to the nearest integer.
+      clamped_value = static_cast<uint8_t>(lrint(double_value));
+    }
+  } else {
+    // Clamp undefined to zero (default). All other types have been
+    // converted to a number type further up in the call chain.
+    DCHECK(value->IsUndefined());
+  }
+  set(index, clamped_value);
+}
+
+
+template <typename ExternalArrayClass, typename ValueType>
+static void ExternalArrayIntSetter(ExternalArrayClass* receiver, uint32_t index,
+                                   Object* value) {
+  ValueType cast_value = 0;
+  if (value->IsSmi()) {
+    int int_value = Smi::cast(value)->value();
+    cast_value = static_cast<ValueType>(int_value);
+  } else if (value->IsHeapNumber()) {
+    double double_value = HeapNumber::cast(value)->value();
+    cast_value = static_cast<ValueType>(DoubleToInt32(double_value));
+  } else {
+    // Clamp undefined to zero (default). All other types have been
+    // converted to a number type further up in the call chain.
+    DCHECK(value->IsUndefined());
+  }
+  receiver->set(index, cast_value);
+}
+
+
+void ExternalInt8Array::SetValue(uint32_t index, Object* value) {
+  ExternalArrayIntSetter<ExternalInt8Array, int8_t>(this, index, value);
+}
+
+
+void ExternalUint8Array::SetValue(uint32_t index, Object* value) {
+  ExternalArrayIntSetter<ExternalUint8Array, uint8_t>(this, index, value);
+}
+
+
+void ExternalInt16Array::SetValue(uint32_t index, Object* value) {
+  ExternalArrayIntSetter<ExternalInt16Array, int16_t>(this, index, value);
+}
+
+
+void ExternalUint16Array::SetValue(uint32_t index, Object* value) {
+  ExternalArrayIntSetter<ExternalUint16Array, uint16_t>(this, index, value);
+}
+
+
+void ExternalInt32Array::SetValue(uint32_t index, Object* value) {
+  ExternalArrayIntSetter<ExternalInt32Array, int32_t>(this, index, value);
+}
+
+
+void ExternalUint32Array::SetValue(uint32_t index, Object* value) {
+  uint32_t cast_value = 0;
+  if (value->IsSmi()) {
+    int int_value = Smi::cast(value)->value();
+    cast_value = static_cast<uint32_t>(int_value);
+  } else if (value->IsHeapNumber()) {
+    double double_value = HeapNumber::cast(value)->value();
+    cast_value = static_cast<uint32_t>(DoubleToUint32(double_value));
+  } else {
+    // Clamp undefined to zero (default). All other types have been
+    // converted to a number type further up in the call chain.
+    DCHECK(value->IsUndefined());
+  }
+  set(index, cast_value);
+}
+
+
+void ExternalFloat32Array::SetValue(uint32_t index, Object* value) {
+  float cast_value = std::numeric_limits<float>::quiet_NaN();
+  if (value->IsSmi()) {
+    int int_value = Smi::cast(value)->value();
+    cast_value = static_cast<float>(int_value);
+  } else if (value->IsHeapNumber()) {
+    double double_value = HeapNumber::cast(value)->value();
+    cast_value = static_cast<float>(double_value);
+  } else {
+    // Clamp undefined to NaN (default). All other types have been
+    // converted to a number type further up in the call chain.
+    DCHECK(value->IsUndefined());
+  }
+  set(index, cast_value);
+}
+
+
+void ExternalFloat64Array::SetValue(uint32_t index, Object* value) {
+  double double_value = std::numeric_limits<double>::quiet_NaN();
+  if (value->IsNumber()) {
+    double_value = value->Number();
+  } else {
+    // Clamp undefined to NaN (default). All other types have been
+    // converted to a number type further up in the call chain.
+    DCHECK(value->IsUndefined());
+  }
+  set(index, double_value);
+}
+
+
 void GlobalObject::InvalidatePropertyCell(Handle<GlobalObject> global,
                                           Handle<Name> name) {
   DCHECK(!global->HasFastProperties());
@@ -15581,6 +15731,21 @@ void JSArrayBuffer::Neuter() {
 }
 
 
+static ElementsKind FixedToExternalElementsKind(ElementsKind elements_kind) {
+  switch (elements_kind) {
+#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
+    case TYPE##_ELEMENTS: return EXTERNAL_##TYPE##_ELEMENTS;
+
+    TYPED_ARRAYS(TYPED_ARRAY_CASE)
+#undef TYPED_ARRAY_CASE
+
+    default:
+      UNREACHABLE();
+      return FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND;
+  }
+}
+
+
 Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
     Handle<JSTypedArray> typed_array) {
 
@@ -15589,6 +15754,10 @@ Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
 
   DCHECK(IsFixedTypedArrayElementsKind(map->elements_kind()));
 
+  Handle<Map> new_map = Map::TransitionElementsTo(
+          map,
+          FixedToExternalElementsKind(map->elements_kind()));
+
   Handle<FixedTypedArrayBase> fixed_typed_array(
       FixedTypedArrayBase::cast(typed_array->elements()));
 
@@ -15605,19 +15774,19 @@ Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
   memcpy(buffer->backing_store(),
          fixed_typed_array->DataPtr(),
          fixed_typed_array->DataSize());
-  Handle<FixedTypedArrayBase> new_elements =
-      isolate->factory()->NewFixedTypedArrayWithExternalPointer(
+  Handle<ExternalArray> new_elements =
+      isolate->factory()->NewExternalArray(
           fixed_typed_array->length(), typed_array->type(),
           static_cast<uint8_t*>(buffer->backing_store()));
 
-  typed_array->set_elements(*new_elements);
+  JSObject::SetMapAndElements(typed_array, new_map, new_elements);
 
   return buffer;
 }
 
 
 Handle<JSArrayBuffer> JSTypedArray::GetBuffer() {
-  if (JSArrayBuffer::cast(buffer())->backing_store() != nullptr) {
+  if (IsExternalArrayElementsKind(map()->elements_kind())) {
     Handle<Object> result(buffer(), GetIsolate());
     return Handle<JSArrayBuffer>::cast(result);
   }
index 7c5b982aeda1bea9735ce7000ae76fc019dfc3a7..342a00e1edb8caeee89eb74d2a5cbf14579cf3b0 100644 (file)
 //         - ScriptContextTable
 //         - WeakFixedArray
 //       - FixedDoubleArray
+//       - ExternalArray
+//         - ExternalUint8ClampedArray
+//         - ExternalInt8Array
+//         - ExternalUint8Array
+//         - ExternalInt16Array
+//         - ExternalUint16Array
+//         - ExternalInt32Array
+//         - ExternalUint32Array
+//         - ExternalFloat32Array
 //     - Name
 //       - String
 //         - SeqString
@@ -383,6 +392,18 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
   V(BYTE_ARRAY_TYPE)                                            \
   V(BYTECODE_ARRAY_TYPE)                                        \
   V(FREE_SPACE_TYPE)                                            \
+  /* Note: the order of these external array */                 \
+  /* types is relied upon in */                                 \
+  /* Object::IsExternalArray(). */                              \
+  V(EXTERNAL_INT8_ARRAY_TYPE)                                   \
+  V(EXTERNAL_UINT8_ARRAY_TYPE)                                  \
+  V(EXTERNAL_INT16_ARRAY_TYPE)                                  \
+  V(EXTERNAL_UINT16_ARRAY_TYPE)                                 \
+  V(EXTERNAL_INT32_ARRAY_TYPE)                                  \
+  V(EXTERNAL_UINT32_ARRAY_TYPE)                                 \
+  V(EXTERNAL_FLOAT32_ARRAY_TYPE)                                \
+  V(EXTERNAL_FLOAT64_ARRAY_TYPE)                                \
+  V(EXTERNAL_UINT8_CLAMPED_ARRAY_TYPE)                          \
                                                                 \
   V(FIXED_INT8_ARRAY_TYPE)                                      \
   V(FIXED_UINT8_ARRAY_TYPE)                                     \
@@ -668,6 +689,15 @@ enum InstanceType {
   BYTE_ARRAY_TYPE,
   BYTECODE_ARRAY_TYPE,
   FREE_SPACE_TYPE,
+  EXTERNAL_INT8_ARRAY_TYPE,  // FIRST_EXTERNAL_ARRAY_TYPE
+  EXTERNAL_UINT8_ARRAY_TYPE,
+  EXTERNAL_INT16_ARRAY_TYPE,
+  EXTERNAL_UINT16_ARRAY_TYPE,
+  EXTERNAL_INT32_ARRAY_TYPE,
+  EXTERNAL_UINT32_ARRAY_TYPE,
+  EXTERNAL_FLOAT32_ARRAY_TYPE,
+  EXTERNAL_FLOAT64_ARRAY_TYPE,
+  EXTERNAL_UINT8_CLAMPED_ARRAY_TYPE,  // LAST_EXTERNAL_ARRAY_TYPE
   FIXED_INT8_ARRAY_TYPE,              // FIRST_FIXED_TYPED_ARRAY_TYPE
   FIXED_UINT8_ARRAY_TYPE,
   FIXED_INT16_ARRAY_TYPE,
@@ -750,6 +780,9 @@ enum InstanceType {
   // Boundaries for testing for a SIMD type.
   FIRST_SIMD_TYPE = FLOAT32X4_TYPE,
   LAST_SIMD_TYPE = FLOAT32X4_TYPE,
+  // Boundaries for testing for an external array.
+  FIRST_EXTERNAL_ARRAY_TYPE = EXTERNAL_INT8_ARRAY_TYPE,
+  LAST_EXTERNAL_ARRAY_TYPE = EXTERNAL_UINT8_CLAMPED_ARRAY_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,
@@ -779,6 +812,9 @@ enum InstanceType {
   NUM_OF_CALLABLE_SPEC_OBJECT_TYPES = 2
 };
 
+const int kExternalArrayTypeCount =
+    LAST_EXTERNAL_ARRAY_TYPE - FIRST_EXTERNAL_ARRAY_TYPE + 1;
+
 STATIC_ASSERT(JS_OBJECT_TYPE == Internals::kJSObjectType);
 STATIC_ASSERT(FIRST_NONSTRING_TYPE == Internals::kFirstNonstringType);
 STATIC_ASSERT(ODDBALL_TYPE == Internals::kOddballType);
@@ -897,6 +933,16 @@ template <class C> inline bool Is(Object* obj);
   V(InternalizedString)            \
   V(Symbol)                        \
                                    \
+  V(ExternalArray)                 \
+  V(ExternalInt8Array)             \
+  V(ExternalUint8Array)            \
+  V(ExternalInt16Array)            \
+  V(ExternalUint16Array)           \
+  V(ExternalInt32Array)            \
+  V(ExternalUint32Array)           \
+  V(ExternalFloat32Array)          \
+  V(ExternalFloat64Array)          \
+  V(ExternalUint8ClampedArray)     \
   V(FixedTypedArrayBase)           \
   V(FixedUint8Array)               \
   V(FixedInt8Array)                \
@@ -1726,8 +1772,9 @@ class JSObject: public JSReceiver {
   // writing to any element the array must be copied. Use
   // EnsureWritableFastElements in this case.
   //
-  // In the slow mode the elements is either a NumberDictionary, a
-  // FixedArray parameter map for a (sloppy) arguments object.
+  // In the slow mode the elements is either a NumberDictionary, an
+  // ExternalArray, or a FixedArray parameter map for a (sloppy)
+  // arguments object.
   DECL_ACCESSORS(elements, FixedArrayBase)
   inline void initialize_elements();
   static void ResetElements(Handle<JSObject> object);
@@ -1754,6 +1801,17 @@ class JSObject: public JSReceiver {
   inline bool HasSloppyArgumentsElements();
   inline bool HasDictionaryElements();
 
+  inline bool HasExternalUint8ClampedElements();
+  inline bool HasExternalArrayElements();
+  inline bool HasExternalInt8Elements();
+  inline bool HasExternalUint8Elements();
+  inline bool HasExternalInt16Elements();
+  inline bool HasExternalUint16Elements();
+  inline bool HasExternalInt32Elements();
+  inline bool HasExternalUint32Elements();
+  inline bool HasExternalFloat32Elements();
+  inline bool HasExternalFloat64Elements();
+
   inline bool HasFixedTypedArrayElements();
 
   inline bool HasFixedUint8ClampedElements();
@@ -4273,14 +4331,261 @@ class FreeSpace: public HeapObject {
   V(Uint8Clamped, uint8_clamped, UINT8_CLAMPED, uint8_t, 1)
 
 
+
+// An ExternalArray represents a fixed-size array of primitive values
+// which live outside the JavaScript heap. Its subclasses are used to
+// implement the CanvasArray types being defined in the WebGL
+// specification. As of this writing the first public draft is not yet
+// available, but Khronos members can access the draft at:
+//   https://cvs.khronos.org/svn/repos/3dweb/trunk/doc/spec/WebGL-spec.html
+//
+// The semantics of these arrays differ from CanvasPixelArray.
+// Out-of-range values passed to the setter are converted via a C
+// cast, not clamping. Out-of-range indices cause exceptions to be
+// raised rather than being silently ignored.
+class ExternalArray: public FixedArrayBase {
+ public:
+  inline bool is_the_hole(int index) { return false; }
+
+  // [external_pointer]: The pointer to the external memory area backing this
+  // external array.
+  DECL_ACCESSORS(external_pointer, void)  // Pointer to the data store.
+
+  DECLARE_CAST(ExternalArray)
+
+  // Maximal acceptable length for an external array.
+  static const int kMaxLength = 0x3fffffff;
+
+  // ExternalArray headers are not quadword aligned.
+  static const int kExternalPointerOffset =
+      POINTER_SIZE_ALIGN(FixedArrayBase::kLengthOffset + kPointerSize);
+  static const int kSize = kExternalPointerOffset + kPointerSize;
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalArray);
+};
+
+
+// A ExternalUint8ClampedArray represents a fixed-size byte array with special
+// semantics used for implementing the CanvasPixelArray object. Please see the
+// specification at:
+
+// http://www.whatwg.org/specs/web-apps/current-work/
+//                      multipage/the-canvas-element.html#canvaspixelarray
+// In particular, write access clamps the value written to 0 or 255 if the
+// value written is outside this range.
+class ExternalUint8ClampedArray: public ExternalArray {
+ public:
+  inline uint8_t* external_uint8_clamped_pointer();
+
+  // Setter and getter.
+  inline uint8_t get_scalar(int index);
+  static inline Handle<Object> get(Handle<ExternalUint8ClampedArray> array,
+                                   int index);
+  inline void set(int index, uint8_t value);
+
+  // This accessor applies the correct conversion from Smi, HeapNumber
+  // and undefined and clamps the converted value between 0 and 255.
+  void SetValue(uint32_t index, Object* value);
+
+  DECLARE_CAST(ExternalUint8ClampedArray)
+
+  // Dispatched behavior.
+  DECLARE_PRINTER(ExternalUint8ClampedArray)
+  DECLARE_VERIFIER(ExternalUint8ClampedArray)
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUint8ClampedArray);
+};
+
+
+class ExternalInt8Array: public ExternalArray {
+ public:
+  // Setter and getter.
+  inline int8_t get_scalar(int index);
+  static inline Handle<Object> get(Handle<ExternalInt8Array> array, int index);
+  inline void set(int index, int8_t value);
+
+  // This accessor applies the correct conversion from Smi, HeapNumber
+  // and undefined.
+  void SetValue(uint32_t index, Object* value);
+
+  DECLARE_CAST(ExternalInt8Array)
+
+  // Dispatched behavior.
+  DECLARE_PRINTER(ExternalInt8Array)
+  DECLARE_VERIFIER(ExternalInt8Array)
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalInt8Array);
+};
+
+
+class ExternalUint8Array: public ExternalArray {
+ public:
+  // Setter and getter.
+  inline uint8_t get_scalar(int index);
+  static inline Handle<Object> get(Handle<ExternalUint8Array> array, int index);
+  inline void set(int index, uint8_t value);
+
+  // This accessor applies the correct conversion from Smi, HeapNumber
+  // and undefined.
+  void SetValue(uint32_t index, Object* value);
+
+  DECLARE_CAST(ExternalUint8Array)
+
+  // Dispatched behavior.
+  DECLARE_PRINTER(ExternalUint8Array)
+  DECLARE_VERIFIER(ExternalUint8Array)
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUint8Array);
+};
+
+
+class ExternalInt16Array: public ExternalArray {
+ public:
+  // Setter and getter.
+  inline int16_t get_scalar(int index);
+  static inline Handle<Object> get(Handle<ExternalInt16Array> array, int index);
+  inline void set(int index, int16_t value);
+
+  // This accessor applies the correct conversion from Smi, HeapNumber
+  // and undefined.
+  void SetValue(uint32_t index, Object* value);
+
+  DECLARE_CAST(ExternalInt16Array)
+
+  // Dispatched behavior.
+  DECLARE_PRINTER(ExternalInt16Array)
+  DECLARE_VERIFIER(ExternalInt16Array)
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalInt16Array);
+};
+
+
+class ExternalUint16Array: public ExternalArray {
+ public:
+  // Setter and getter.
+  inline uint16_t get_scalar(int index);
+  static inline Handle<Object> get(Handle<ExternalUint16Array> array,
+                                   int index);
+  inline void set(int index, uint16_t value);
+
+  // This accessor applies the correct conversion from Smi, HeapNumber
+  // and undefined.
+  void SetValue(uint32_t index, Object* value);
+
+  DECLARE_CAST(ExternalUint16Array)
+
+  // Dispatched behavior.
+  DECLARE_PRINTER(ExternalUint16Array)
+  DECLARE_VERIFIER(ExternalUint16Array)
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUint16Array);
+};
+
+
+class ExternalInt32Array: public ExternalArray {
+ public:
+  // Setter and getter.
+  inline int32_t get_scalar(int index);
+  static inline Handle<Object> get(Handle<ExternalInt32Array> array, int index);
+  inline void set(int index, int32_t value);
+
+  // This accessor applies the correct conversion from Smi, HeapNumber
+  // and undefined.
+  void SetValue(uint32_t index, Object* value);
+
+  DECLARE_CAST(ExternalInt32Array)
+
+  // Dispatched behavior.
+  DECLARE_PRINTER(ExternalInt32Array)
+  DECLARE_VERIFIER(ExternalInt32Array)
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalInt32Array);
+};
+
+
+class ExternalUint32Array: public ExternalArray {
+ public:
+  // Setter and getter.
+  inline uint32_t get_scalar(int index);
+  static inline Handle<Object> get(Handle<ExternalUint32Array> array,
+                                   int index);
+  inline void set(int index, uint32_t value);
+
+  // This accessor applies the correct conversion from Smi, HeapNumber
+  // and undefined.
+  void SetValue(uint32_t index, Object* value);
+
+  DECLARE_CAST(ExternalUint32Array)
+
+  // Dispatched behavior.
+  DECLARE_PRINTER(ExternalUint32Array)
+  DECLARE_VERIFIER(ExternalUint32Array)
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUint32Array);
+};
+
+
+class ExternalFloat32Array: public ExternalArray {
+ public:
+  // Setter and getter.
+  inline float get_scalar(int index);
+  static inline Handle<Object> get(Handle<ExternalFloat32Array> array,
+                                   int index);
+  inline void set(int index, float value);
+
+  // This accessor applies the correct conversion from Smi, HeapNumber
+  // and undefined.
+  void SetValue(uint32_t index, Object* value);
+
+  DECLARE_CAST(ExternalFloat32Array)
+
+  // Dispatched behavior.
+  DECLARE_PRINTER(ExternalFloat32Array)
+  DECLARE_VERIFIER(ExternalFloat32Array)
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalFloat32Array);
+};
+
+
+class ExternalFloat64Array: public ExternalArray {
+ public:
+  // Setter and getter.
+  inline double get_scalar(int index);
+  static inline Handle<Object> get(Handle<ExternalFloat64Array> array,
+                                   int index);
+  inline void set(int index, double value);
+
+  // This accessor applies the correct conversion from Smi, HeapNumber
+  // and undefined.
+  void SetValue(uint32_t index, Object* value);
+
+  DECLARE_CAST(ExternalFloat64Array)
+
+  // Dispatched behavior.
+  DECLARE_PRINTER(ExternalFloat64Array)
+  DECLARE_VERIFIER(ExternalFloat64Array)
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalFloat64Array);
+};
+
+
 class FixedTypedArrayBase: public FixedArrayBase {
  public:
-  // [base_pointer]: Either points to the FixedTypedArrayBase itself or nullptr.
+  // [base_pointer]: For now, points to the FixedTypedArrayBase itself.
   DECL_ACCESSORS(base_pointer, Object)
 
-  // [external_pointer]: Contains the offset between base_pointer and the start
-  // of the data. If the base_pointer is a nullptr, the external_pointer
-  // therefore points to the actual backing store.
+  // [external_pointer]: For now, contains the offset between base_pointer and
+  // the start of the data.
   DECL_ACCESSORS(external_pointer, void)
 
   // Dispatched behavior.
@@ -5431,6 +5736,10 @@ class Map: public HeapObject {
     return IsSloppyArgumentsElements(elements_kind());
   }
 
+  inline bool has_external_array_elements() {
+    return IsExternalArrayElementsKind(elements_kind());
+  }
+
   inline bool has_fixed_typed_array_elements() {
     return IsFixedTypedArrayElementsKind(elements_kind());
   }
index dc9790b98847155ae52166718461fddd3ad73ac5..bb7287c625850894e4e044368603076b1d538bc8 100644 (file)
@@ -3297,7 +3297,10 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
   bool key_is_smi = instr->hydrogen()->key()->representation().IsSmi();
   int base_offset = instr->base_offset();
 
-  if (elements_kind == FLOAT32_ELEMENTS || elements_kind == FLOAT64_ELEMENTS) {
+  if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+      elements_kind == FLOAT32_ELEMENTS ||
+      elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
+      elements_kind == FLOAT64_ELEMENTS) {
     DoubleRegister result = ToDoubleRegister(instr->result());
     if (key_is_constant) {
       __ Add(scratch0(), external_pointer, constant_key << element_size_shift,
@@ -3306,7 +3309,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
       __ IndexToArrayOffset(r0, key, element_size_shift, key_is_smi);
       __ add(scratch0(), external_pointer, r0);
     }
-    if (elements_kind == FLOAT32_ELEMENTS) {
+    if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+        elements_kind == FLOAT32_ELEMENTS) {
       __ lfs(result, MemOperand(scratch0(), base_offset));
     } else {  // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS
       __ lfd(result, MemOperand(scratch0(), base_offset));
@@ -3317,6 +3321,7 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
         PrepareKeyedOperand(key, external_pointer, key_is_constant, key_is_smi,
                             constant_key, element_size_shift, base_offset);
     switch (elements_kind) {
+      case EXTERNAL_INT8_ELEMENTS:
       case INT8_ELEMENTS:
         if (key_is_constant) {
           __ LoadByte(result, mem_operand, r0);
@@ -3325,6 +3330,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
         }
         __ extsb(result, result);
         break;
+      case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
+      case EXTERNAL_UINT8_ELEMENTS:
       case UINT8_ELEMENTS:
       case UINT8_CLAMPED_ELEMENTS:
         if (key_is_constant) {
@@ -3333,6 +3340,7 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
           __ lbzx(result, mem_operand);
         }
         break;
+      case EXTERNAL_INT16_ELEMENTS:
       case INT16_ELEMENTS:
         if (key_is_constant) {
           __ LoadHalfWordArith(result, mem_operand, r0);
@@ -3340,6 +3348,7 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
           __ lhax(result, mem_operand);
         }
         break;
+      case EXTERNAL_UINT16_ELEMENTS:
       case UINT16_ELEMENTS:
         if (key_is_constant) {
           __ LoadHalfWord(result, mem_operand, r0);
@@ -3347,6 +3356,7 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
           __ lhzx(result, mem_operand);
         }
         break;
+      case EXTERNAL_INT32_ELEMENTS:
       case INT32_ELEMENTS:
         if (key_is_constant) {
           __ LoadWordArith(result, mem_operand, r0);
@@ -3354,6 +3364,7 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
           __ lwax(result, mem_operand);
         }
         break;
+      case EXTERNAL_UINT32_ELEMENTS:
       case UINT32_ELEMENTS:
         if (key_is_constant) {
           __ LoadWord(result, mem_operand, r0);
@@ -3368,6 +3379,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
         break;
       case FLOAT32_ELEMENTS:
       case FLOAT64_ELEMENTS:
+      case EXTERNAL_FLOAT32_ELEMENTS:
+      case EXTERNAL_FLOAT64_ELEMENTS:
       case FAST_HOLEY_DOUBLE_ELEMENTS:
       case FAST_HOLEY_ELEMENTS:
       case FAST_HOLEY_SMI_ELEMENTS:
@@ -3504,7 +3517,7 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
 
 
 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
-  if (instr->is_fixed_typed_array()) {
+  if (instr->is_typed_elements()) {
     DoLoadKeyedExternalArray(instr);
   } else if (instr->hydrogen()->representation().IsDouble()) {
     DoLoadKeyedFixedDoubleArray(instr);
@@ -4558,7 +4571,10 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
   bool key_is_smi = instr->hydrogen()->key()->representation().IsSmi();
   int base_offset = instr->base_offset();
 
-  if (elements_kind == FLOAT32_ELEMENTS || elements_kind == FLOAT64_ELEMENTS) {
+  if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+      elements_kind == FLOAT32_ELEMENTS ||
+      elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
+      elements_kind == FLOAT64_ELEMENTS) {
     Register address = scratch0();
     DoubleRegister value(ToDoubleRegister(instr->value()));
     if (key_is_constant) {
@@ -4572,7 +4588,8 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
       __ IndexToArrayOffset(r0, key, element_size_shift, key_is_smi);
       __ add(address, external_pointer, r0);
     }
-    if (elements_kind == FLOAT32_ELEMENTS) {
+    if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+        elements_kind == FLOAT32_ELEMENTS) {
       __ frsp(double_scratch0(), value);
       __ stfs(double_scratch0(), MemOperand(address, base_offset));
     } else {  // Storing doubles, not floats.
@@ -4584,6 +4601,9 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
         PrepareKeyedOperand(key, external_pointer, key_is_constant, key_is_smi,
                             constant_key, element_size_shift, base_offset);
     switch (elements_kind) {
+      case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
+      case EXTERNAL_INT8_ELEMENTS:
+      case EXTERNAL_UINT8_ELEMENTS:
       case UINT8_ELEMENTS:
       case UINT8_CLAMPED_ELEMENTS:
       case INT8_ELEMENTS:
@@ -4593,6 +4613,8 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
           __ stbx(value, mem_operand);
         }
         break;
+      case EXTERNAL_INT16_ELEMENTS:
+      case EXTERNAL_UINT16_ELEMENTS:
       case INT16_ELEMENTS:
       case UINT16_ELEMENTS:
         if (key_is_constant) {
@@ -4601,6 +4623,8 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
           __ sthx(value, mem_operand);
         }
         break;
+      case EXTERNAL_INT32_ELEMENTS:
+      case EXTERNAL_UINT32_ELEMENTS:
       case INT32_ELEMENTS:
       case UINT32_ELEMENTS:
         if (key_is_constant) {
@@ -4611,6 +4635,8 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
         break;
       case FLOAT32_ELEMENTS:
       case FLOAT64_ELEMENTS:
+      case EXTERNAL_FLOAT32_ELEMENTS:
+      case EXTERNAL_FLOAT64_ELEMENTS:
       case FAST_DOUBLE_ELEMENTS:
       case FAST_ELEMENTS:
       case FAST_SMI_ELEMENTS:
@@ -4728,7 +4754,7 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
 
 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
   // By cases: external, fast double
-  if (instr->is_fixed_typed_array()) {
+  if (instr->is_typed_elements()) {
     DoStoreKeyedExternalArray(instr);
   } else if (instr->hydrogen()->value()->representation().IsDouble()) {
     DoStoreKeyedFixedDoubleArray(instr);
index 19ea818a35d0985425920c4c12d01a042ee3fd3a..92dc76b22d8e17ffde2921c47c53ed22bb10a4da 100644 (file)
@@ -2198,7 +2198,7 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
   LOperand* key = UseRegisterOrConstantAtStart(instr->key());
   LInstruction* result = NULL;
 
-  if (!instr->is_fixed_typed_array()) {
+  if (!instr->is_typed_elements()) {
     LOperand* obj = NULL;
     if (instr->representation().IsDouble()) {
       obj = UseRegister(instr->elements());
@@ -2216,9 +2216,10 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
   }
 
   bool needs_environment;
-  if (instr->is_fixed_typed_array()) {
+  if (instr->is_external() || instr->is_fixed_typed_array()) {
     // see LCodeGen::DoLoadKeyedExternalArray
-    needs_environment = elements_kind == UINT32_ELEMENTS &&
+    needs_environment = (elements_kind == EXTERNAL_UINT32_ELEMENTS ||
+                         elements_kind == UINT32_ELEMENTS) &&
                         !instr->CheckFlag(HInstruction::kUint32);
   } else {
     // see LCodeGen::DoLoadKeyedFixedDoubleArray and
@@ -2252,7 +2253,7 @@ LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
 
 
 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
-  if (!instr->is_fixed_typed_array()) {
+  if (!instr->is_typed_elements()) {
     DCHECK(instr->elements()->representation().IsTagged());
     bool needs_write_barrier = instr->NeedsWriteBarrier();
     LOperand* object = NULL;
index dbf980321e0a96e3c01e5f554e13184d810d0e53..f2426d0d550d0039135951c17b30eed3dac32fae 100644 (file)
@@ -1587,9 +1587,13 @@ class LLoadKeyed final : public LTemplateInstruction<1, 2, 0> {
   LOperand* elements() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
   ElementsKind elements_kind() const { return hydrogen()->elements_kind(); }
+  bool is_external() const { return hydrogen()->is_external(); }
   bool is_fixed_typed_array() const {
     return hydrogen()->is_fixed_typed_array();
   }
+  bool is_typed_elements() const {
+    return is_external() || is_fixed_typed_array();
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
   DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
@@ -2164,9 +2168,13 @@ class LStoreKeyed final : public LTemplateInstruction<0, 3, 0> {
     inputs_[2] = value;
   }
 
+  bool is_external() const { return hydrogen()->is_external(); }
   bool is_fixed_typed_array() const {
     return hydrogen()->is_fixed_typed_array();
   }
+  bool is_typed_elements() const {
+    return is_external() || is_fixed_typed_array();
+  }
   LOperand* elements() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
   LOperand* value() { return inputs_[2]; }
index b5655db611a5ce34161d45990718872fa7f02916..af2d4c54813104a5e9566293951e9c488822b9fd 100644 (file)
@@ -298,6 +298,7 @@ static uint32_t EstimateElementCount(Handle<JSArray> array) {
     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
+  case EXTERNAL_##TYPE##_ELEMENTS:                      \
   case TYPE##_ELEMENTS:
 
       TYPED_ARRAYS(TYPED_ARRAY_CASE)
@@ -417,6 +418,7 @@ static void CollectElementIndices(Handle<JSObject> object, uint32_t range,
     }
 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
   case TYPE##_ELEMENTS:                                 \
+  case EXTERNAL_##TYPE##_ELEMENTS:
 
       TYPED_ARRAYS(TYPED_ARRAY_CASE)
 #undef TYPED_ARRAY_CASE
@@ -608,6 +610,15 @@ static bool IterateElements(Isolate* isolate, Handle<JSObject> receiver,
       }
       break;
     }
+    case EXTERNAL_UINT8_CLAMPED_ELEMENTS: {
+      Handle<ExternalUint8ClampedArray> pixels(
+          ExternalUint8ClampedArray::cast(receiver->elements()));
+      for (uint32_t j = 0; j < length; j++) {
+        Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate);
+        visitor->visit(j, e);
+      }
+      break;
+    }
     case UINT8_CLAMPED_ELEMENTS: {
       Handle<FixedUint8ClampedArray> pixels(
       FixedUint8ClampedArray::cast(receiver->elements()));
@@ -617,41 +628,81 @@ static bool IterateElements(Isolate* isolate, Handle<JSObject> receiver,
       }
       break;
     }
+    case EXTERNAL_INT8_ELEMENTS: {
+      IterateTypedArrayElements<ExternalInt8Array, int8_t>(
+          isolate, receiver, true, true, visitor);
+      break;
+    }
     case INT8_ELEMENTS: {
       IterateTypedArrayElements<FixedInt8Array, int8_t>(
       isolate, receiver, true, true, visitor);
       break;
     }
+    case EXTERNAL_UINT8_ELEMENTS: {
+      IterateTypedArrayElements<ExternalUint8Array, uint8_t>(
+          isolate, receiver, true, true, visitor);
+      break;
+    }
     case UINT8_ELEMENTS: {
       IterateTypedArrayElements<FixedUint8Array, uint8_t>(
       isolate, receiver, true, true, visitor);
       break;
     }
+    case EXTERNAL_INT16_ELEMENTS: {
+      IterateTypedArrayElements<ExternalInt16Array, int16_t>(
+          isolate, receiver, true, true, visitor);
+      break;
+    }
     case INT16_ELEMENTS: {
       IterateTypedArrayElements<FixedInt16Array, int16_t>(
       isolate, receiver, true, true, visitor);
       break;
     }
+    case EXTERNAL_UINT16_ELEMENTS: {
+      IterateTypedArrayElements<ExternalUint16Array, uint16_t>(
+          isolate, receiver, true, true, visitor);
+      break;
+    }
     case UINT16_ELEMENTS: {
       IterateTypedArrayElements<FixedUint16Array, uint16_t>(
       isolate, receiver, true, true, visitor);
       break;
     }
+    case EXTERNAL_INT32_ELEMENTS: {
+      IterateTypedArrayElements<ExternalInt32Array, int32_t>(
+          isolate, receiver, true, false, visitor);
+      break;
+    }
     case INT32_ELEMENTS: {
       IterateTypedArrayElements<FixedInt32Array, int32_t>(
       isolate, receiver, true, false, visitor);
       break;
     }
+    case EXTERNAL_UINT32_ELEMENTS: {
+      IterateTypedArrayElements<ExternalUint32Array, uint32_t>(
+          isolate, receiver, true, false, visitor);
+      break;
+    }
     case UINT32_ELEMENTS: {
       IterateTypedArrayElements<FixedUint32Array, uint32_t>(
       isolate, receiver, true, false, visitor);
       break;
     }
+    case EXTERNAL_FLOAT32_ELEMENTS: {
+      IterateTypedArrayElements<ExternalFloat32Array, float>(
+          isolate, receiver, false, false, visitor);
+      break;
+    }
     case FLOAT32_ELEMENTS: {
       IterateTypedArrayElements<FixedFloat32Array, float>(
       isolate, receiver, false, false, visitor);
       break;
     }
+    case EXTERNAL_FLOAT64_ELEMENTS: {
+      IterateTypedArrayElements<ExternalFloat64Array, double>(
+          isolate, receiver, false, false, visitor);
+      break;
+    }
     case FLOAT64_ELEMENTS: {
       IterateTypedArrayElements<FixedFloat64Array, double>(
       isolate, receiver, false, false, visitor);
@@ -1182,7 +1233,8 @@ RUNTIME_FUNCTION(Runtime_NormalizeElements) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
-  RUNTIME_ASSERT(!array->HasFixedTypedArrayElements() &&
+  RUNTIME_ASSERT(!array->HasExternalArrayElements() &&
+                 !array->HasFixedTypedArrayElements() &&
                  !array->IsJSGlobalProxy());
   JSObject::NormalizeElements(array);
   return *array;
index 7ae885e2f6ffee6fe7b01caa6be2d80ad4a3c5bd..6422efdaa6a1f544a141c55fceb92e935a86931c 100644 (file)
@@ -480,13 +480,24 @@ ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements)
 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SloppyArgumentsElements)
-ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FixedTypedArrayElements)
+ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
 // Properties test sitting with elements tests - not fooling anyone.
 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties)
 
 #undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
 
 
+#define TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, size) \
+  RUNTIME_FUNCTION(Runtime_HasExternal##Type##Elements) {                  \
+    CONVERT_ARG_CHECKED(JSObject, obj, 0);                                 \
+    return isolate->heap()->ToBoolean(obj->HasExternal##Type##Elements()); \
+  }
+
+TYPED_ARRAYS(TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
+
+#undef TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
+
+
 #define FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, s) \
   RUNTIME_FUNCTION(Runtime_HasFixed##Type##Elements) {                        \
     CONVERT_ARG_CHECKED(JSObject, obj, 0);                                    \
index bfb810e76d9cf16a580d601993cc3956ce40bae3..4d355247037e57e46c0130b01a39f9b1068b4da0 100644 (file)
@@ -159,12 +159,14 @@ RUNTIME_FUNCTION(Runtime_ArrayBufferNeuter) {
 
 
 void Runtime::ArrayIdToTypeAndSize(int arrayId, ExternalArrayType* array_type,
+                                   ElementsKind* external_elements_kind,
                                    ElementsKind* fixed_elements_kind,
                                    size_t* element_size) {
   switch (arrayId) {
 #define ARRAY_ID_CASE(Type, type, TYPE, ctype, size)      \
   case ARRAY_ID_##TYPE:                                   \
     *array_type = kExternal##Type##Array;                 \
+    *external_elements_kind = EXTERNAL_##TYPE##_ELEMENTS; \
     *fixed_elements_kind = TYPE##_ELEMENTS;               \
     *element_size = size;                                 \
     break;
@@ -193,9 +195,11 @@ RUNTIME_FUNCTION(Runtime_TypedArrayInitialize) {
 
   ExternalArrayType array_type = kExternalInt8Array;  // Bogus initialization.
   size_t element_size = 1;                            // Bogus initialization.
+  ElementsKind external_elements_kind =
+      EXTERNAL_INT8_ELEMENTS;                        // Bogus initialization.
   ElementsKind fixed_elements_kind = INT8_ELEMENTS;  // Bogus initialization.
-  Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &fixed_elements_kind,
-                                &element_size);
+  Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &external_elements_kind,
+                                &fixed_elements_kind, &element_size);
   RUNTIME_ASSERT(holder->map()->elements_kind() == fixed_elements_kind);
 
   size_t byte_offset = 0;
@@ -237,11 +241,13 @@ RUNTIME_FUNCTION(Runtime_TypedArrayInitialize) {
     Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(maybe_buffer);
     holder->set_buffer(*buffer);
 
-    Handle<FixedTypedArrayBase> elements =
-        isolate->factory()->NewFixedTypedArrayWithExternalPointer(
-            static_cast<int>(length), array_type,
-            static_cast<uint8_t*>(buffer->backing_store()) + byte_offset);
-    holder->set_elements(*elements);
+    Handle<ExternalArray> elements = isolate->factory()->NewExternalArray(
+        static_cast<int>(length), array_type,
+        static_cast<uint8_t*>(buffer->backing_store()) + byte_offset);
+    Handle<Map> map =
+        JSObject::GetElementsTransitionMap(holder, external_elements_kind);
+    JSObject::SetMapAndElements(holder, map, elements);
+    DCHECK(IsExternalArrayElementsKind(holder->map()->elements_kind()));
   } else {
     Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
     Runtime::SetupArrayBuffer(isolate, buffer, true, NULL, byte_length,
@@ -274,9 +280,11 @@ RUNTIME_FUNCTION(Runtime_TypedArrayInitializeFromArrayLike) {
 
   ExternalArrayType array_type = kExternalInt8Array;  // Bogus initialization.
   size_t element_size = 1;                            // Bogus initialization.
+  ElementsKind external_elements_kind =
+      EXTERNAL_INT8_ELEMENTS;                        // Bogus intialization.
   ElementsKind fixed_elements_kind = INT8_ELEMENTS;  // Bogus initialization.
-  Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &fixed_elements_kind,
-                                &element_size);
+  Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &external_elements_kind,
+                                &fixed_elements_kind, &element_size);
 
   RUNTIME_ASSERT(holder->map()->elements_kind() == fixed_elements_kind);
 
@@ -332,11 +340,12 @@ RUNTIME_FUNCTION(Runtime_TypedArrayInitializeFromArrayLike) {
   holder->set_byte_length(*byte_length_obj);
   holder->set_length(*length_obj);
 
-  Handle<FixedTypedArrayBase> elements =
-      isolate->factory()->NewFixedTypedArrayWithExternalPointer(
-          static_cast<int>(length), array_type,
-          static_cast<uint8_t*>(buffer->backing_store()));
-  holder->set_elements(*elements);
+  Handle<ExternalArray> elements = isolate->factory()->NewExternalArray(
+      static_cast<int>(length), array_type,
+      static_cast<uint8_t*>(buffer->backing_store()));
+  Handle<Map> map =
+      JSObject::GetElementsTransitionMap(holder, external_elements_kind);
+  JSObject::SetMapAndElements(holder, map, elements);
 
   if (source->IsJSTypedArray()) {
     Handle<JSTypedArray> typed_array(JSTypedArray::cast(*source));
index dcd0e4ce62d8a304dfa5971c265dc04ba5316124..1e2471cf95287f12ffe4c8132630e5d039fa8c66 100644 (file)
@@ -658,8 +658,17 @@ namespace internal {
   F(HasFastHoleyElements, 1, 1)               \
   F(HasDictionaryElements, 1, 1)              \
   F(HasSloppyArgumentsElements, 1, 1)         \
-  F(HasFixedTypedArrayElements, 1, 1)         \
+  F(HasExternalArrayElements, 1, 1)           \
   F(HasFastProperties, 1, 1)                  \
+  F(HasExternalUint8Elements, 1, 1)           \
+  F(HasExternalInt8Elements, 1, 1)            \
+  F(HasExternalUint16Elements, 1, 1)          \
+  F(HasExternalInt16Elements, 1, 1)           \
+  F(HasExternalUint32Elements, 1, 1)          \
+  F(HasExternalInt32Elements, 1, 1)           \
+  F(HasExternalFloat32Elements, 1, 1)         \
+  F(HasExternalFloat64Elements, 1, 1)         \
+  F(HasExternalUint8ClampedElements, 1, 1)    \
   F(HasFixedUint8Elements, 1, 1)              \
   F(HasFixedInt8Elements, 1, 1)               \
   F(HasFixedUint16Elements, 1, 1)             \
@@ -918,6 +927,7 @@ class Runtime : public AllStatic {
   };
 
   static void ArrayIdToTypeAndSize(int array_id, ExternalArrayType* type,
+                                   ElementsKind* external_elements_kind,
                                    ElementsKind* fixed_elements_kind,
                                    size_t* element_size);
 
index 387949b2dfec1a58c7600a15a56499ee5dd5c9f5..a4c36b893fc906a10ee698ba17d0a82873dd6d27 100644 (file)
@@ -3116,31 +3116,40 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
       elements_kind,
       instr->base_offset()));
 
-  if (elements_kind == FLOAT32_ELEMENTS) {
+  if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+      elements_kind == FLOAT32_ELEMENTS) {
     XMMRegister result(ToDoubleRegister(instr->result()));
     __ movss(result, operand);
     __ cvtss2sd(result, result);
-  } else if (elements_kind == FLOAT64_ELEMENTS) {
+  } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
+             elements_kind == FLOAT64_ELEMENTS) {
     __ movsd(ToDoubleRegister(instr->result()), operand);
   } else {
     Register result(ToRegister(instr->result()));
     switch (elements_kind) {
+      case EXTERNAL_INT8_ELEMENTS:
       case INT8_ELEMENTS:
         __ movsxbl(result, operand);
         break;
+      case EXTERNAL_UINT8_ELEMENTS:
+      case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
       case UINT8_ELEMENTS:
       case UINT8_CLAMPED_ELEMENTS:
         __ movzxbl(result, operand);
         break;
+      case EXTERNAL_INT16_ELEMENTS:
       case INT16_ELEMENTS:
         __ movsxwl(result, operand);
         break;
+      case EXTERNAL_UINT16_ELEMENTS:
       case UINT16_ELEMENTS:
         __ movzxwl(result, operand);
         break;
+      case EXTERNAL_INT32_ELEMENTS:
       case INT32_ELEMENTS:
         __ movl(result, operand);
         break;
+      case EXTERNAL_UINT32_ELEMENTS:
       case UINT32_ELEMENTS:
         __ movl(result, operand);
         if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
@@ -3148,6 +3157,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
           DeoptimizeIf(negative, instr, Deoptimizer::kNegativeValue);
         }
         break;
+      case EXTERNAL_FLOAT32_ELEMENTS:
+      case EXTERNAL_FLOAT64_ELEMENTS:
       case FLOAT32_ELEMENTS:
       case FLOAT64_ELEMENTS:
       case FAST_ELEMENTS:
@@ -3266,7 +3277,7 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
 
 
 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
-  if (instr->is_fixed_typed_array()) {
+  if (instr->is_typed_elements()) {
     DoLoadKeyedExternalArray(instr);
   } else if (instr->hydrogen()->representation().IsDouble()) {
     DoLoadKeyedFixedDoubleArray(instr);
@@ -4368,28 +4379,39 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
       elements_kind,
       instr->base_offset()));
 
-  if (elements_kind == FLOAT32_ELEMENTS) {
+  if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+      elements_kind == FLOAT32_ELEMENTS) {
     XMMRegister value(ToDoubleRegister(instr->value()));
     __ cvtsd2ss(value, value);
     __ movss(operand, value);
-  } else if (elements_kind == FLOAT64_ELEMENTS) {
+  } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
+             elements_kind == FLOAT64_ELEMENTS) {
     __ movsd(operand, ToDoubleRegister(instr->value()));
   } else {
     Register value(ToRegister(instr->value()));
     switch (elements_kind) {
+      case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
+      case EXTERNAL_INT8_ELEMENTS:
+      case EXTERNAL_UINT8_ELEMENTS:
       case INT8_ELEMENTS:
       case UINT8_ELEMENTS:
       case UINT8_CLAMPED_ELEMENTS:
         __ movb(operand, value);
         break;
+      case EXTERNAL_INT16_ELEMENTS:
+      case EXTERNAL_UINT16_ELEMENTS:
       case INT16_ELEMENTS:
       case UINT16_ELEMENTS:
         __ movw(operand, value);
         break;
+      case EXTERNAL_INT32_ELEMENTS:
+      case EXTERNAL_UINT32_ELEMENTS:
       case INT32_ELEMENTS:
       case UINT32_ELEMENTS:
         __ movl(operand, value);
         break;
+      case EXTERNAL_FLOAT32_ELEMENTS:
+      case EXTERNAL_FLOAT64_ELEMENTS:
       case FLOAT32_ELEMENTS:
       case FLOAT64_ELEMENTS:
       case FAST_ELEMENTS:
@@ -4513,7 +4535,7 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
 
 
 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
-  if (instr->is_fixed_typed_array()) {
+  if (instr->is_typed_elements()) {
     DoStoreKeyedExternalArray(instr);
   } else if (instr->hydrogen()->value()->representation().IsDouble()) {
     DoStoreKeyedFixedDoubleArray(instr);
index 27e79846059ffff4e3e3c05a4133d684818c2968..46bb35ae8f9fab01007ce77bb5186f7dbb58290f 100644 (file)
@@ -2241,7 +2241,7 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
     FindDehoistedKeyDefinitions(instr->key());
   }
 
-  if (!instr->is_fixed_typed_array()) {
+  if (!instr->is_typed_elements()) {
     LOperand* obj = UseRegisterAtStart(instr->elements());
     result = DefineAsRegister(new(zone()) LLoadKeyed(obj, key));
   } else {
@@ -2255,9 +2255,10 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
   }
 
   bool needs_environment;
-  if (instr->is_fixed_typed_array()) {
+  if (instr->is_external() || instr->is_fixed_typed_array()) {
     // see LCodeGen::DoLoadKeyedExternalArray
-    needs_environment = elements_kind == UINT32_ELEMENTS &&
+    needs_environment = (elements_kind == EXTERNAL_UINT32_ELEMENTS ||
+                         elements_kind == UINT32_ELEMENTS) &&
                         !instr->CheckFlag(HInstruction::kUint32);
   } else {
     // see LCodeGen::DoLoadKeyedFixedDoubleArray and
@@ -2297,7 +2298,7 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
     FindDehoistedKeyDefinitions(instr->key());
   }
 
-  if (!instr->is_fixed_typed_array()) {
+  if (!instr->is_typed_elements()) {
     DCHECK(instr->elements()->representation().IsTagged());
     bool needs_write_barrier = instr->NeedsWriteBarrier();
     LOperand* object = NULL;
@@ -2332,8 +2333,10 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
        (instr->value()->representation().IsDouble() &&
        IsDoubleOrFloatElementsKind(elements_kind)));
   DCHECK(instr->elements()->representation().IsExternal());
-  bool val_is_temp_register = elements_kind == UINT8_CLAMPED_ELEMENTS ||
-                              elements_kind == FLOAT32_ELEMENTS;
+  bool val_is_temp_register =
+      elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS ||
+      elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+      elements_kind == FLOAT32_ELEMENTS;
   LOperand* val = val_is_temp_register ? UseTempRegister(instr->value())
       : UseRegister(instr->value());
   LOperand* key = NULL;
index 06158d47976d9eb3c21a8bbb2ced543a6f7bd697..95d56beb2c62bc499f49746ef6b2bb1a7bff9c9a 100644 (file)
@@ -1617,8 +1617,12 @@ inline static bool ExternalArrayOpRequiresTemp(
   // an index cannot fold the scale operation into a load and need an extra
   // temp register to do the work.
   return SmiValuesAre31Bits() && key_representation.IsSmi() &&
-         (elements_kind == UINT8_ELEMENTS || elements_kind == INT8_ELEMENTS ||
-          elements_kind == UINT8_CLAMPED_ELEMENTS);
+      (elements_kind == EXTERNAL_INT8_ELEMENTS ||
+       elements_kind == EXTERNAL_UINT8_ELEMENTS ||
+       elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS ||
+       elements_kind == UINT8_ELEMENTS ||
+       elements_kind == INT8_ELEMENTS ||
+       elements_kind == UINT8_CLAMPED_ELEMENTS);
 }
 
 
@@ -1632,9 +1636,15 @@ class LLoadKeyed final : public LTemplateInstruction<1, 2, 0> {
   DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
   DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
 
+  bool is_external() const {
+    return hydrogen()->is_external();
+  }
   bool is_fixed_typed_array() const {
     return hydrogen()->is_fixed_typed_array();
   }
+  bool is_typed_elements() const {
+    return is_external() || is_fixed_typed_array();
+  }
   LOperand* elements() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
   void PrintDataTo(StringStream* stream) override;
@@ -2225,9 +2235,13 @@ class LStoreKeyed final : public LTemplateInstruction<0, 3, 0> {
     inputs_[2] = value;
   }
 
+  bool is_external() const { return hydrogen()->is_external(); }
   bool is_fixed_typed_array() const {
     return hydrogen()->is_fixed_typed_array();
   }
+  bool is_typed_elements() const {
+    return is_external() || is_fixed_typed_array();
+  }
   LOperand* elements() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
   LOperand* value() { return inputs_[2]; }
index 6e74b45104f3b90991f40cc5116b2c7700b921ac..ee96cf698801e8c1c0deb3c6e53baad5459891ad 100644 (file)
@@ -3344,29 +3344,38 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
       instr->hydrogen()->key()->representation(),
       elements_kind,
       instr->base_offset()));
-  if (elements_kind == FLOAT32_ELEMENTS) {
+  if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+      elements_kind == FLOAT32_ELEMENTS) {
     X87Mov(ToX87Register(instr->result()), operand, kX87FloatOperand);
-  } else if (elements_kind == FLOAT64_ELEMENTS) {
+  } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
+             elements_kind == FLOAT64_ELEMENTS) {
     X87Mov(ToX87Register(instr->result()), operand);
   } else {
     Register result(ToRegister(instr->result()));
     switch (elements_kind) {
+      case EXTERNAL_INT8_ELEMENTS:
       case INT8_ELEMENTS:
         __ movsx_b(result, operand);
         break;
+      case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
+      case EXTERNAL_UINT8_ELEMENTS:
       case UINT8_ELEMENTS:
       case UINT8_CLAMPED_ELEMENTS:
         __ movzx_b(result, operand);
         break;
+      case EXTERNAL_INT16_ELEMENTS:
       case INT16_ELEMENTS:
         __ movsx_w(result, operand);
         break;
+      case EXTERNAL_UINT16_ELEMENTS:
       case UINT16_ELEMENTS:
         __ movzx_w(result, operand);
         break;
+      case EXTERNAL_INT32_ELEMENTS:
       case INT32_ELEMENTS:
         __ mov(result, operand);
         break;
+      case EXTERNAL_UINT32_ELEMENTS:
       case UINT32_ELEMENTS:
         __ mov(result, operand);
         if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
@@ -3374,6 +3383,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
           DeoptimizeIf(negative, instr, Deoptimizer::kNegativeValue);
         }
         break;
+      case EXTERNAL_FLOAT32_ELEMENTS:
+      case EXTERNAL_FLOAT64_ELEMENTS:
       case FLOAT32_ELEMENTS:
       case FLOAT64_ELEMENTS:
       case FAST_SMI_ELEMENTS:
@@ -3452,7 +3463,7 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
 
 
 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
-  if (instr->is_fixed_typed_array()) {
+  if (instr->is_typed_elements()) {
     DoLoadKeyedExternalArray(instr);
   } else if (instr->hydrogen()->representation().IsDouble()) {
     DoLoadKeyedFixedDoubleArray(instr);
@@ -4599,9 +4610,11 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
       instr->hydrogen()->key()->representation(),
       elements_kind,
       instr->base_offset()));
-  if (elements_kind == FLOAT32_ELEMENTS) {
+  if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
+      elements_kind == FLOAT32_ELEMENTS) {
     X87Mov(operand, ToX87Register(instr->value()), kX87FloatOperand);
-  } else if (elements_kind == FLOAT64_ELEMENTS) {
+  } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
+             elements_kind == FLOAT64_ELEMENTS) {
     uint64_t int_val = kHoleNanInt64;
     int32_t lower = static_cast<int32_t>(int_val);
     int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
@@ -4631,19 +4644,28 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
   } else {
     Register value = ToRegister(instr->value());
     switch (elements_kind) {
+      case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
+      case EXTERNAL_UINT8_ELEMENTS:
+      case EXTERNAL_INT8_ELEMENTS:
       case UINT8_ELEMENTS:
       case INT8_ELEMENTS:
       case UINT8_CLAMPED_ELEMENTS:
         __ mov_b(operand, value);
         break;
+      case EXTERNAL_INT16_ELEMENTS:
+      case EXTERNAL_UINT16_ELEMENTS:
       case UINT16_ELEMENTS:
       case INT16_ELEMENTS:
         __ mov_w(operand, value);
         break;
+      case EXTERNAL_INT32_ELEMENTS:
+      case EXTERNAL_UINT32_ELEMENTS:
       case UINT32_ELEMENTS:
       case INT32_ELEMENTS:
         __ mov(operand, value);
         break;
+      case EXTERNAL_FLOAT32_ELEMENTS:
+      case EXTERNAL_FLOAT64_ELEMENTS:
       case FLOAT32_ELEMENTS:
       case FLOAT64_ELEMENTS:
       case FAST_SMI_ELEMENTS:
@@ -4759,7 +4781,7 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
 
 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
   // By cases...external, fast-double, fast
-  if (instr->is_fixed_typed_array()) {
+  if (instr->is_typed_elements()) {
     DoStoreKeyedExternalArray(instr);
   } else if (instr->hydrogen()->value()->representation().IsDouble()) {
     DoStoreKeyedFixedDoubleArray(instr);
index 9e310b2a333eb0416622489d71c88956bcad08cd..2f5f15f2887132d12d63a30090ee82f8713c54e9 100644 (file)
@@ -2240,7 +2240,7 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
       : UseRegisterOrConstantAtStart(instr->key());
   LInstruction* result = NULL;
 
-  if (!instr->is_fixed_typed_array()) {
+  if (!instr->is_typed_elements()) {
     LOperand* obj = UseRegisterAtStart(instr->elements());
     result = DefineAsRegister(new(zone()) LLoadKeyed(obj, key));
   } else {
@@ -2254,9 +2254,10 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
   }
 
   bool needs_environment;
-  if (instr->is_fixed_typed_array()) {
+  if (instr->is_external() || instr->is_fixed_typed_array()) {
     // see LCodeGen::DoLoadKeyedExternalArray
-    needs_environment = elements_kind == UINT32_ELEMENTS &&
+    needs_environment = (elements_kind == EXTERNAL_UINT32_ELEMENTS ||
+                         elements_kind == UINT32_ELEMENTS) &&
                         !instr->CheckFlag(HInstruction::kUint32);
   } else {
     // see LCodeGen::DoLoadKeyedFixedDoubleArray and
@@ -2293,6 +2294,9 @@ LOperand* LChunkBuilder::GetStoreKeyedValueOperand(HStoreKeyed* instr) {
 
   // Determine if we need a byte register in this case for the value.
   bool val_is_fixed_register =
+      elements_kind == EXTERNAL_INT8_ELEMENTS ||
+      elements_kind == EXTERNAL_UINT8_ELEMENTS ||
+      elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS ||
       elements_kind == UINT8_ELEMENTS ||
       elements_kind == INT8_ELEMENTS ||
       elements_kind == UINT8_CLAMPED_ELEMENTS;
@@ -2309,7 +2313,7 @@ LOperand* LChunkBuilder::GetStoreKeyedValueOperand(HStoreKeyed* instr) {
 
 
 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
-  if (!instr->is_fixed_typed_array()) {
+  if (!instr->is_typed_elements()) {
     DCHECK(instr->elements()->representation().IsTagged());
     DCHECK(instr->key()->representation().IsInteger32() ||
            instr->key()->representation().IsSmi());
index cf6c1e181535d238472137676321e264689fdf19..b8f881ddab66388ccc4824ec5da51f4aa879f823 100644 (file)
@@ -1649,9 +1649,15 @@ class LLoadKeyed final : public LTemplateInstruction<1, 2, 0> {
   ElementsKind elements_kind() const {
     return hydrogen()->elements_kind();
   }
+  bool is_external() const {
+    return hydrogen()->is_external();
+  }
   bool is_fixed_typed_array() const {
     return hydrogen()->is_fixed_typed_array();
   }
+  bool is_typed_elements() const {
+    return is_external() || is_fixed_typed_array();
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadKeyed, "load-keyed")
   DECLARE_HYDROGEN_ACCESSOR(LoadKeyed)
@@ -1671,8 +1677,12 @@ inline static bool ExternalArrayOpRequiresTemp(
   // an index cannot fold the scale operation into a load and need an extra
   // temp register to do the work.
   return key_representation.IsSmi() &&
-         (elements_kind == UINT8_ELEMENTS || elements_kind == INT8_ELEMENTS ||
-          elements_kind == UINT8_CLAMPED_ELEMENTS);
+      (elements_kind == EXTERNAL_INT8_ELEMENTS ||
+       elements_kind == EXTERNAL_UINT8_ELEMENTS ||
+       elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS ||
+       elements_kind == UINT8_ELEMENTS ||
+       elements_kind == INT8_ELEMENTS ||
+       elements_kind == UINT8_CLAMPED_ELEMENTS);
 }
 
 
@@ -2253,9 +2263,13 @@ class LStoreKeyed final : public LTemplateInstruction<0, 3, 0> {
     inputs_[2] = val;
   }
 
+  bool is_external() const { return hydrogen()->is_external(); }
   bool is_fixed_typed_array() const {
     return hydrogen()->is_fixed_typed_array();
   }
+  bool is_typed_elements() const {
+    return is_external() || is_fixed_typed_array();
+  }
   LOperand* elements() { return inputs_[0]; }
   LOperand* key() { return inputs_[1]; }
   LOperand* value() { return inputs_[2]; }
index b7677f7fd207fbeafb2b3a7eb8690d2bc9bbf24d..d4442f7a85d6ddfc6f295b3c9e8ba1e087bd350d 100644 (file)
@@ -21,15 +21,16 @@ static void TypedArrayLoadHelper(const char* array_type) {
     values_builder.AddFormatted("a[%d] = 0x%08x;", i, kValues[i]);
   }
 
-  // Note that below source creates two different typed arrays with the same
-  // elements kind to get coverage for both (on heap / with external backing
-  // store) access patterns.
+  // Note that below source creates two different typed arrays with distinct
+  // elements kind to get coverage for both access patterns:
+  // - IsFixedTypedArrayElementsKind(x)
+  // - IsExternalArrayElementsKind(y)
   const char* source =
       "(function(a) {"
       "  var x = (a = new %sArray(%d)); %s;"
       "  var y = (a = new %sArray(%d)); %s; %%TypedArrayGetBuffer(y);"
       "  if (!%%HasFixed%sElements(x)) %%AbortJS('x');"
-      "  if (!%%HasFixed%sElements(y)) %%AbortJS('y');"
+      "  if (!%%HasExternal%sElements(y)) %%AbortJS('y');"
       "  function f(a,b) {"
       "    a = a | 0; b = b | 0;"
       "    return x[a] + y[b];"
@@ -83,15 +84,16 @@ static void TypedArrayStoreHelper(const char* array_type) {
     values_builder.AddFormatted("a[%d] = 0x%08x;", i, kValues[i]);
   }
 
-  // Note that below source creates two different typed arrays with the same
-  // elements kind to get coverage for both (on heap/with external backing
-  // store) access patterns.
+  // Note that below source creates two different typed arrays with distinct
+  // elements kind to get coverage for both access patterns:
+  // - IsFixedTypedArrayElementsKind(x)
+  // - IsExternalArrayElementsKind(y)
   const char* source =
       "(function(a) {"
       "  var x = (a = new %sArray(%d)); %s;"
       "  var y = (a = new %sArray(%d)); %s; %%TypedArrayGetBuffer(y);"
       "  if (!%%HasFixed%sElements(x)) %%AbortJS('x');"
-      "  if (!%%HasFixed%sElements(y)) %%AbortJS('y');"
+      "  if (!%%HasExternal%sElements(y)) %%AbortJS('y');"
       "  function f(a,b) {"
       "    a = a | 0; b = b | 0;"
       "    var t = x[a];"
index f4d346330671b4a5ece30a15af2780ceb8db1d83..df32722e634e201921c7fbb439c66958ac917d5c 100644 (file)
@@ -14149,58 +14149,58 @@ void TypedArrayTestHelper(i::ExternalArrayType array_type, int64_t low,
 
 
 THREADED_TEST(Uint8Array) {
-  TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
+  TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUint8Array,
                        v8::ArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
 }
 
 
 THREADED_TEST(Int8Array) {
-  TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
+  TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalInt8Array,
                        v8::ArrayBuffer>(i::kExternalInt8Array, -0x80, 0x7F);
 }
 
 
 THREADED_TEST(Uint16Array) {
-  TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
+  TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::ExternalUint16Array,
                        v8::ArrayBuffer>(i::kExternalUint16Array, 0, 0xFFFF);
 }
 
 
 THREADED_TEST(Int16Array) {
-  TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
+  TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalInt16Array,
                        v8::ArrayBuffer>(i::kExternalInt16Array, -0x8000,
                                         0x7FFF);
 }
 
 
 THREADED_TEST(Uint32Array) {
-  TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
+  TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUint32Array,
                        v8::ArrayBuffer>(i::kExternalUint32Array, 0, UINT_MAX);
 }
 
 
 THREADED_TEST(Int32Array) {
-  TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
+  TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalInt32Array,
                        v8::ArrayBuffer>(i::kExternalInt32Array, INT_MIN,
                                         INT_MAX);
 }
 
 
 THREADED_TEST(Float32Array) {
-  TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
+  TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloat32Array,
                        v8::ArrayBuffer>(i::kExternalFloat32Array, -500, 500);
 }
 
 
 THREADED_TEST(Float64Array) {
-  TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
+  TypedArrayTestHelper<double, v8::Float64Array, i::ExternalFloat64Array,
                        v8::ArrayBuffer>(i::kExternalFloat64Array, -500, 500);
 }
 
 
 THREADED_TEST(Uint8ClampedArray) {
   TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
-                       i::FixedUint8ClampedArray, v8::ArrayBuffer>(
+                       i::ExternalUint8ClampedArray, v8::ArrayBuffer>(
       i::kExternalUint8ClampedArray, 0, 0xFF);
 }
 
@@ -14226,14 +14226,14 @@ THREADED_TEST(DataView) {
 
 THREADED_TEST(SharedUint8Array) {
   i::FLAG_harmony_sharedarraybuffer = true;
-  TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
+  TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUint8Array,
                        v8::SharedArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
 }
 
 
 THREADED_TEST(SharedInt8Array) {
   i::FLAG_harmony_sharedarraybuffer = true;
-  TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
+  TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalInt8Array,
                        v8::SharedArrayBuffer>(i::kExternalInt8Array, -0x80,
                                               0x7F);
 }
@@ -14241,7 +14241,7 @@ THREADED_TEST(SharedInt8Array) {
 
 THREADED_TEST(SharedUint16Array) {
   i::FLAG_harmony_sharedarraybuffer = true;
-  TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
+  TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::ExternalUint16Array,
                        v8::SharedArrayBuffer>(i::kExternalUint16Array, 0,
                                               0xFFFF);
 }
@@ -14249,7 +14249,7 @@ THREADED_TEST(SharedUint16Array) {
 
 THREADED_TEST(SharedInt16Array) {
   i::FLAG_harmony_sharedarraybuffer = true;
-  TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
+  TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalInt16Array,
                        v8::SharedArrayBuffer>(i::kExternalInt16Array, -0x8000,
                                               0x7FFF);
 }
@@ -14257,7 +14257,7 @@ THREADED_TEST(SharedInt16Array) {
 
 THREADED_TEST(SharedUint32Array) {
   i::FLAG_harmony_sharedarraybuffer = true;
-  TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
+  TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUint32Array,
                        v8::SharedArrayBuffer>(i::kExternalUint32Array, 0,
                                               UINT_MAX);
 }
@@ -14265,7 +14265,7 @@ THREADED_TEST(SharedUint32Array) {
 
 THREADED_TEST(SharedInt32Array) {
   i::FLAG_harmony_sharedarraybuffer = true;
-  TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
+  TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalInt32Array,
                        v8::SharedArrayBuffer>(i::kExternalInt32Array, INT_MIN,
                                               INT_MAX);
 }
@@ -14273,7 +14273,7 @@ THREADED_TEST(SharedInt32Array) {
 
 THREADED_TEST(SharedFloat32Array) {
   i::FLAG_harmony_sharedarraybuffer = true;
-  TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
+  TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloat32Array,
                        v8::SharedArrayBuffer>(i::kExternalFloat32Array, -500,
                                               500);
 }
@@ -14281,7 +14281,7 @@ THREADED_TEST(SharedFloat32Array) {
 
 THREADED_TEST(SharedFloat64Array) {
   i::FLAG_harmony_sharedarraybuffer = true;
-  TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
+  TypedArrayTestHelper<double, v8::Float64Array, i::ExternalFloat64Array,
                        v8::SharedArrayBuffer>(i::kExternalFloat64Array, -500,
                                               500);
 }
@@ -14290,7 +14290,7 @@ THREADED_TEST(SharedFloat64Array) {
 THREADED_TEST(SharedUint8ClampedArray) {
   i::FLAG_harmony_sharedarraybuffer = true;
   TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
-                       i::FixedUint8ClampedArray, v8::SharedArrayBuffer>(
+                       i::ExternalUint8ClampedArray, v8::SharedArrayBuffer>(
       i::kExternalUint8ClampedArray, 0, 0xFF);
 }
 
index 4da8a9dc60843cbaff12193c6db3766079c4ae83..cb2d178a7e3f0886e9a585cb0163ed5eac362d10 100644 (file)
@@ -32,6 +32,15 @@ var elements_kind = {
   fast                      :  'fast elements',
   fast_double               :  'fast double elements',
   dictionary                :  'dictionary elements',
+  external_int32            :  'external int8 elements',
+  external_uint8            :  'external uint8 elements',
+  external_int16            :  'external int16 elements',
+  external_uint16           :  'external uint16 elements',
+  external_int32            :  'external int32 elements',
+  external_uint32           :  'external uint32 elements',
+  external_float32          :  'external float32 elements',
+  external_float64          :  'external float64 elements',
+  external_uint8_clamped    :  'external uint8_clamped elements',
   fixed_int32               :  'fixed int8 elements',
   fixed_uint8               :  'fixed uint8 elements',
   fixed_int16               :  'fixed int16 elements',
@@ -49,6 +58,34 @@ function getKind(obj) {
   if (%HasFastDoubleElements(obj)) return elements_kind.fast_double;
   if (%HasDictionaryElements(obj)) return elements_kind.dictionary;
 
+  // Every external kind is also an external array.
+  if (%HasExternalInt8Elements(obj)) {
+    return elements_kind.external_int8;
+  }
+  if (%HasExternalUint8Elements(obj)) {
+    return elements_kind.external_uint8;
+  }
+  if (%HasExternalInt16Elements(obj)) {
+    return elements_kind.external_int16;
+  }
+  if (%HasExternalUint16Elements(obj)) {
+    return elements_kind.external_uint16;
+  }
+  if (%HasExternalInt32Elements(obj)) {
+    return elements_kind.external_int32;
+  }
+  if (%HasExternalUint32Elements(obj)) {
+    return elements_kind.external_uint32;
+  }
+  if (%HasExternalFloat32Elements(obj)) {
+    return elements_kind.external_float32;
+  }
+  if (%HasExternalFloat64Elements(obj)) {
+    return elements_kind.external_float64;
+  }
+  if (%HasExternalUint8ClampedElements(obj)) {
+    return elements_kind.external_uint8_clamped;
+  }
   if (%HasFixedInt8Elements(obj)) {
     return elements_kind.fixed_int8;
   }
@@ -127,15 +164,15 @@ function test_wrapper() {
   assertKind(elements_kind.fixed_uint8_clamped, new Uint8ClampedArray(512));
 
   var ab = new ArrayBuffer(128);
-  assertKind(elements_kind.fixed_int8,    new Int8Array(ab));
-  assertKind(elements_kind.fixed_uint8,   new Uint8Array(ab));
-  assertKind(elements_kind.fixed_int16,   new Int16Array(ab));
-  assertKind(elements_kind.fixed_uint16,  new Uint16Array(ab));
-  assertKind(elements_kind.fixed_int32,   new Int32Array(ab));
-  assertKind(elements_kind.fixed_uint32,  new Uint32Array(ab));
-  assertKind(elements_kind.fixed_float32, new Float32Array(ab));
-  assertKind(elements_kind.fixed_float64, new Float64Array(ab));
-  assertKind(elements_kind.fixed_uint8_clamped, new Uint8ClampedArray(ab));
+  assertKind(elements_kind.external_int8,    new Int8Array(ab));
+  assertKind(elements_kind.external_uint8,   new Uint8Array(ab));
+  assertKind(elements_kind.external_int16,   new Int16Array(ab));
+  assertKind(elements_kind.external_uint16,  new Uint16Array(ab));
+  assertKind(elements_kind.external_int32,   new Int32Array(ab));
+  assertKind(elements_kind.external_uint32,  new Uint32Array(ab));
+  assertKind(elements_kind.external_float32, new Float32Array(ab));
+  assertKind(elements_kind.external_float64, new Float64Array(ab));
+  assertKind(elements_kind.external_uint8_clamped, new Uint8ClampedArray(ab));
 
   // Crankshaft support for smi-only array elements.
   function monomorphic(array) {
index 515305a928880ad72937a3fab21b9efa66907feb..5f4f437299a5551d6c0075095630b5209bacb3f6 100644 (file)
 // Flags: --stress-runs=2
 
 var elements_kind = {
-  fast_smi_only             :  'fast smi only elements',
-  fast                      :  'fast elements',
-  fast_double               :  'fast double elements',
-  dictionary                :  'dictionary elements',
-  fixed_int32               :  'fixed int8 elements',
-  fixed_uint8               :  'fixed uint8 elements',
-  fixed_int16               :  'fixed int16 elements',
-  fixed_uint16              :  'fixed uint16 elements',
-  fixed_int32               :  'fixed int32 elements',
-  fixed_uint32              :  'fixed uint32 elements',
-  fixed_float32             :  'fixed float32 elements',
-  fixed_float64             :  'fixed float64 elements',
-  fixed_uint8_clamped       :  'fixed uint8_clamped elements'
+  fast_smi_only            :  'fast smi only elements',
+  fast                     :  'fast elements',
+  fast_double              :  'fast double elements',
+  dictionary               :  'dictionary elements',
+  external_byte            :  'external byte elements',
+  external_unsigned_byte   :  'external unsigned byte elements',
+  external_short           :  'external short elements',
+  external_unsigned_short  :  'external unsigned short elements',
+  external_int             :  'external int elements',
+  external_unsigned_int    :  'external unsigned int elements',
+  external_float           :  'external float elements',
+  external_double          :  'external double elements',
+  external_pixel           :  'external pixel elements'
 }
 
 function getKind(obj) {
@@ -53,33 +53,34 @@ function getKind(obj) {
   if (%HasFastObjectElements(obj)) return elements_kind.fast;
   if (%HasFastDoubleElements(obj)) return elements_kind.fast_double;
   if (%HasDictionaryElements(obj)) return elements_kind.dictionary;
-
-  if (%HasFixedInt8Elements(obj)) {
-    return elements_kind.fixed_int8;
+  // Every external kind is also an external array.
+  assertTrue(%HasExternalArrayElements(obj));
+  if (%HasExternalByteElements(obj)) {
+    return elements_kind.external_byte;
   }
-  if (%HasFixedUint8Elements(obj)) {
-    return elements_kind.fixed_uint8;
+  if (%HasExternalUnsignedByteElements(obj)) {
+    return elements_kind.external_unsigned_byte;
   }
-  if (%HasFixedInt16Elements(obj)) {
-    return elements_kind.fixed_int16;
+  if (%HasExternalShortElements(obj)) {
+    return elements_kind.external_short;
   }
-  if (%HasFixedUint16Elements(obj)) {
-    return elements_kind.fixed_uint16;
+  if (%HasExternalUnsignedShortElements(obj)) {
+    return elements_kind.external_unsigned_short;
   }
-  if (%HasFixedInt32Elements(obj)) {
-    return elements_kind.fixed_int32;
+  if (%HasExternalIntElements(obj)) {
+    return elements_kind.external_int;
   }
-  if (%HasFixedUint32Elements(obj)) {
-    return elements_kind.fixed_uint32;
+  if (%HasExternalUnsignedIntElements(obj)) {
+    return elements_kind.external_unsigned_int;
   }
-  if (%HasFixedFloat32Elements(obj)) {
-    return elements_kind.fixed_float32;
+  if (%HasExternalFloatElements(obj)) {
+    return elements_kind.external_float;
   }
-  if (%HasFixedFloat64Elements(obj)) {
-    return elements_kind.fixed_float64;
+  if (%HasExternalDoubleElements(obj)) {
+    return elements_kind.external_double;
   }
-  if (%HasFixedUint8ClampedElements(obj)) {
-    return elements_kind.fixed_uint8_clamped;
+  if (%HasExternalPixelElements(obj)) {
+    return elements_kind.external_pixel;
   }
 }
 
index bd15ef37e4ef65283c02702598c61ca43478018a..389b6dac6f7f5cb90980f2895e20464befe392bd 100644 (file)
 // Flags: --stress-runs=2
 
 var elements_kind = {
-  fast_smi_only             :  'fast smi only elements',
-  fast                      :  'fast elements',
-  fast_double               :  'fast double elements',
-  dictionary                :  'dictionary elements',
-  fixed_int32               :  'fixed int8 elements',
-  fixed_uint8               :  'fixed uint8 elements',
-  fixed_int16               :  'fixed int16 elements',
-  fixed_uint16              :  'fixed uint16 elements',
-  fixed_int32               :  'fixed int32 elements',
-  fixed_uint32              :  'fixed uint32 elements',
-  fixed_float32             :  'fixed float32 elements',
-  fixed_float64             :  'fixed float64 elements',
-  fixed_uint8_clamped       :  'fixed uint8_clamped elements'
+  fast_smi_only            :  'fast smi only elements',
+  fast                     :  'fast elements',
+  fast_double              :  'fast double elements',
+  dictionary               :  'dictionary elements',
+  external_byte            :  'external byte elements',
+  external_unsigned_byte   :  'external unsigned byte elements',
+  external_short           :  'external short elements',
+  external_unsigned_short  :  'external unsigned short elements',
+  external_int             :  'external int elements',
+  external_unsigned_int    :  'external unsigned int elements',
+  external_float           :  'external float elements',
+  external_double          :  'external double elements',
+  external_pixel           :  'external pixel elements'
 }
 
 function getKind(obj) {
@@ -53,33 +53,34 @@ function getKind(obj) {
   if (%HasFastObjectElements(obj)) return elements_kind.fast;
   if (%HasFastDoubleElements(obj)) return elements_kind.fast_double;
   if (%HasDictionaryElements(obj)) return elements_kind.dictionary;
-
-  if (%HasFixedInt8Elements(obj)) {
-    return elements_kind.fixed_int8;
+  // Every external kind is also an external array.
+  assertTrue(%HasExternalArrayElements(obj));
+  if (%HasExternalByteElements(obj)) {
+    return elements_kind.external_byte;
   }
-  if (%HasFixedUint8Elements(obj)) {
-    return elements_kind.fixed_uint8;
+  if (%HasExternalUnsignedByteElements(obj)) {
+    return elements_kind.external_unsigned_byte;
   }
-  if (%HasFixedInt16Elements(obj)) {
-    return elements_kind.fixed_int16;
+  if (%HasExternalShortElements(obj)) {
+    return elements_kind.external_short;
   }
-  if (%HasFixedUint16Elements(obj)) {
-    return elements_kind.fixed_uint16;
+  if (%HasExternalUnsignedShortElements(obj)) {
+    return elements_kind.external_unsigned_short;
   }
-  if (%HasFixedInt32Elements(obj)) {
-    return elements_kind.fixed_int32;
+  if (%HasExternalIntElements(obj)) {
+    return elements_kind.external_int;
   }
-  if (%HasFixedUint32Elements(obj)) {
-    return elements_kind.fixed_uint32;
+  if (%HasExternalUnsignedIntElements(obj)) {
+    return elements_kind.external_unsigned_int;
   }
-  if (%HasFixedFloat32Elements(obj)) {
-    return elements_kind.fixed_float32;
+  if (%HasExternalFloatElements(obj)) {
+    return elements_kind.external_float;
   }
-  if (%HasFixedFloat64Elements(obj)) {
-    return elements_kind.fixed_float64;
+  if (%HasExternalDoubleElements(obj)) {
+    return elements_kind.external_double;
   }
-  if (%HasFixedUint8ClampedElements(obj)) {
-    return elements_kind.fixed_uint8_clamped;
+  if (%HasExternalPixelElements(obj)) {
+    return elements_kind.external_pixel;
   }
 }