Unify internal and external typed arrays a bit
authorjochen <jochen@chromium.org>
Thu, 30 Apr 2015 13:46:27 +0000 (06:46 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 30 Apr 2015 13:46:34 +0000 (13:46 +0000)
Just give internal ones an ArrayBuffer with a NULL backing store. This
simplifies the access checks a lot.

BUG=v8:3996
R=hpayer@chromium.org,verwaest@chromium.org
LOG=n

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

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

19 files changed:
include/v8.h
src/api.cc
src/arm/lithium-codegen-arm.cc
src/arm64/lithium-codegen-arm64.cc
src/bootstrapper.cc
src/contexts.h
src/factory.cc
src/hydrogen-instructions.h
src/hydrogen.cc
src/hydrogen.h
src/ia32/lithium-codegen-ia32.cc
src/mips/lithium-codegen-mips.cc
src/mips64/lithium-codegen-mips64.cc
src/objects-inl.h
src/objects.cc
src/ppc/lithium-codegen-ppc.cc
src/runtime/runtime-typedarray.cc
src/x64/lithium-codegen-x64.cc
src/x87/lithium-codegen-x87.cc

index 9103845..73e5e5c 100644 (file)
@@ -6670,7 +6670,7 @@ class Internals {
   static const int kJSObjectHeaderSize = 3 * kApiPointerSize;
   static const int kFixedArrayHeaderSize = 2 * kApiPointerSize;
   static const int kContextHeaderSize = 2 * kApiPointerSize;
-  static const int kContextEmbedderDataIndex = 76;
+  static const int kContextEmbedderDataIndex = 77;
   static const int kFullStringRepresentationMask = 0x07;
   static const int kStringEncodingMask = 0x4;
   static const int kExternalTwoByteRepresentationTag = 0x02;
index c42cab6..a750c0c 100644 (file)
@@ -6336,31 +6336,21 @@ Local<ArrayBuffer> v8::ArrayBufferView::Buffer() {
 
 
 size_t v8::ArrayBufferView::CopyContents(void* dest, size_t byte_length) {
-  i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
-  i::Isolate* isolate = obj->GetIsolate();
-  size_t byte_offset = i::NumberToSize(isolate, obj->byte_offset());
+  i::Handle<i::JSArrayBufferView> self = Utils::OpenHandle(this);
+  i::Isolate* isolate = self->GetIsolate();
+  size_t byte_offset = i::NumberToSize(isolate, self->byte_offset());
   size_t bytes_to_copy =
-      i::Min(byte_length, i::NumberToSize(isolate, obj->byte_length()));
+      i::Min(byte_length, i::NumberToSize(isolate, self->byte_length()));
   if (bytes_to_copy) {
     i::DisallowHeapAllocation no_gc;
-    const char* source = nullptr;
-    if (obj->IsJSDataView()) {
-      i::Handle<i::JSDataView> data_view(i::JSDataView::cast(*obj));
-      i::Handle<i::JSArrayBuffer> buffer(
-          i::JSArrayBuffer::cast(data_view->buffer()));
-      source = reinterpret_cast<char*>(buffer->backing_store());
-    } else {
-      DCHECK(obj->IsJSTypedArray());
-      i::Handle<i::JSTypedArray> typed_array(i::JSTypedArray::cast(*obj));
-      if (typed_array->buffer()->IsSmi()) {
-        i::Handle<i::FixedTypedArrayBase> fixed_array(
-            i::FixedTypedArrayBase::cast(typed_array->elements()));
-        source = reinterpret_cast<char*>(fixed_array->DataPtr());
-      } else {
-        i::Handle<i::JSArrayBuffer> buffer(
-            i::JSArrayBuffer::cast(typed_array->buffer()));
-        source = reinterpret_cast<char*>(buffer->backing_store());
-      }
+    i::Handle<i::JSArrayBuffer> buffer(i::JSArrayBuffer::cast(self->buffer()));
+    const char* source = reinterpret_cast<char*>(buffer->backing_store());
+    if (source == nullptr) {
+      DCHECK(self->IsJSTypedArray());
+      i::Handle<i::JSTypedArray> typed_array(i::JSTypedArray::cast(*self));
+      i::Handle<i::FixedTypedArrayBase> fixed_array(
+          i::FixedTypedArrayBase::cast(typed_array->elements()));
+      source = reinterpret_cast<char*>(fixed_array->DataPtr());
     }
     memcpy(dest, source + byte_offset, bytes_to_copy);
   }
@@ -6369,11 +6359,9 @@ size_t v8::ArrayBufferView::CopyContents(void* dest, size_t byte_length) {
 
 
 bool v8::ArrayBufferView::HasBuffer() const {
-  i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
-  if (obj->IsJSDataView()) return true;
-  DCHECK(obj->IsJSTypedArray());
-  i::Handle<i::JSTypedArray> typed_array(i::JSTypedArray::cast(*obj));
-  return !typed_array->buffer()->IsSmi();
+  i::Handle<i::JSArrayBufferView> self = Utils::OpenHandle(this);
+  i::Handle<i::JSArrayBuffer> buffer(i::JSArrayBuffer::cast(self->buffer()));
+  return buffer->backing_store() != nullptr;
 }
 
 
index be7958e..b480fd9 100644 (file)
@@ -5163,14 +5163,10 @@ void LCodeGen::DoCheckArrayBufferNotNeutered(
   Register view = ToRegister(instr->view());
   Register scratch = scratch0();
 
-  Label has_no_buffer;
   __ ldr(scratch, FieldMemOperand(view, JSArrayBufferView::kBufferOffset));
-  __ JumpIfSmi(scratch, &has_no_buffer);
   __ ldr(scratch, FieldMemOperand(scratch, JSArrayBuffer::kBitFieldOffset));
   __ tst(scratch, Operand(1 << JSArrayBuffer::WasNeutered::kShift));
   DeoptimizeIf(ne, instr, Deoptimizer::kOutOfBounds);
-
-  __ bind(&has_no_buffer);
 }
 
 
index badd177..a249ca4 100644 (file)
@@ -2235,14 +2235,10 @@ void LCodeGen::DoCheckArrayBufferNotNeutered(
   Register view = ToRegister(instr->view());
   Register scratch = temps.AcquireX();
 
-  Label has_no_buffer;
   __ Ldr(scratch, FieldMemOperand(view, JSArrayBufferView::kBufferOffset));
-  __ JumpIfSmi(scratch, &has_no_buffer);
   __ Ldr(scratch, FieldMemOperand(scratch, JSArrayBuffer::kBitFieldOffset));
   __ Tst(scratch, Operand(1 << JSArrayBuffer::WasNeutered::kShift));
   DeoptimizeIf(ne, instr, Deoptimizer::kOutOfBounds);
-
-  __ Bind(&has_no_buffer);
 }
 
 
index cf79f37..4117ce0 100644 (file)
@@ -1151,6 +1151,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> global_object,
             isolate->initial_object_prototype(),
             Builtins::kIllegal);
     native_context()->set_array_buffer_fun(*array_buffer_fun);
+    native_context()->set_array_buffer_map(array_buffer_fun->initial_map());
   }
 
   {  // -- T y p e d A r r a y s
index 4fe0621..2d04da2 100644 (file)
@@ -101,6 +101,7 @@ enum BindingFlags {
   V(TO_LENGTH_FUN_INDEX, JSFunction, to_length_fun)                            \
   V(GLOBAL_EVAL_FUN_INDEX, JSFunction, global_eval_fun)                        \
   V(ARRAY_BUFFER_FUN_INDEX, JSFunction, array_buffer_fun)                      \
+  V(ARRAY_BUFFER_MAP_INDEX, Map, array_buffer_map)                             \
   V(UINT8_ARRAY_FUN_INDEX, JSFunction, uint8_array_fun)                        \
   V(INT8_ARRAY_FUN_INDEX, JSFunction, int8_array_fun)                          \
   V(UINT16_ARRAY_FUN_INDEX, JSFunction, uint16_array_fun)                      \
@@ -352,6 +353,7 @@ class Context: public FixedArray {
     TO_BOOLEAN_FUN_INDEX,
     GLOBAL_EVAL_FUN_INDEX,
     ARRAY_BUFFER_FUN_INDEX,
+    ARRAY_BUFFER_MAP_INDEX,
     UINT8_ARRAY_FUN_INDEX,
     INT8_ARRAY_FUN_INDEX,
     UINT16_ARRAY_FUN_INDEX,
index ddb6a64..3df71b1 100644 (file)
@@ -1987,7 +1987,9 @@ Handle<JSTypedArray> Factory::NewJSTypedArray(ElementsKind elements_kind,
   Handle<Object> length_object = NewNumberFromSize(number_of_elements);
   obj->set_length(*length_object);
 
-  obj->set_buffer(Smi::FromInt(0));
+  Handle<JSArrayBuffer> buffer = isolate()->factory()->NewJSArrayBuffer();
+  Runtime::SetupArrayBuffer(isolate(), buffer, true, NULL, byte_length);
+  obj->set_buffer(*buffer);
   Handle<FixedTypedArrayBase> elements =
       isolate()->factory()->NewFixedTypedArray(
           static_cast<int>(number_of_elements), array_type);
index 6f56c76..e49e860 100644 (file)
@@ -6130,6 +6130,11 @@ class HObjectAccess final {
         JSArrayBuffer::kBitFieldOffset, Representation::Integer32());
   }
 
+  static HObjectAccess ForJSArrayBufferBitFieldSlot() {
+    return HObjectAccess::ForObservableJSObjectOffset(
+        JSArrayBuffer::kBitFieldSlot, Representation::Smi());
+  }
+
   static HObjectAccess ForExternalArrayExternalPointer() {
     return HObjectAccess::ForObservableJSObjectOffset(
         ExternalArray::kExternalPointerOffset, Representation::External());
index 5827059..e03a205 100644 (file)
@@ -3191,29 +3191,21 @@ HValue* HGraphBuilder::BuildArrayBufferViewFieldAccessor(HValue* object,
       object, checked_object, HObjectAccess::ForJSArrayBufferViewBuffer());
   HInstruction* field = Add<HLoadNamedField>(object, checked_object, access);
 
-  IfBuilder if_has_buffer(this);
-  HValue* has_buffer = if_has_buffer.IfNot<HIsSmiAndBranch>(buffer);
-  if_has_buffer.Then();
-  {
-    HInstruction* flags = Add<HLoadNamedField>(
-        buffer, has_buffer, HObjectAccess::ForJSArrayBufferBitField());
-    HValue* was_neutered_mask =
-        Add<HConstant>(1 << JSArrayBuffer::WasNeutered::kShift);
-    HValue* was_neutered_test =
-        AddUncasted<HBitwise>(Token::BIT_AND, flags, was_neutered_mask);
-
-    IfBuilder if_was_neutered(this);
-    if_was_neutered.If<HCompareNumericAndBranch>(
-        was_neutered_test, graph()->GetConstant0(), Token::NE);
-    if_was_neutered.Then();
-    Push(graph()->GetConstant0());
-    if_was_neutered.Else();
-    Push(field);
-    if_was_neutered.End();
-  }
-  if_has_buffer.Else();
+  HInstruction* flags = Add<HLoadNamedField>(
+      buffer, nullptr, HObjectAccess::ForJSArrayBufferBitField());
+  HValue* was_neutered_mask =
+      Add<HConstant>(1 << JSArrayBuffer::WasNeutered::kShift);
+  HValue* was_neutered_test =
+      AddUncasted<HBitwise>(Token::BIT_AND, flags, was_neutered_mask);
+
+  IfBuilder if_was_neutered(this);
+  if_was_neutered.If<HCompareNumericAndBranch>(
+      was_neutered_test, graph()->GetConstant0(), Token::NE);
+  if_was_neutered.Then();
+  Push(graph()->GetConstant0());
+  if_was_neutered.Else();
   Push(field);
-  if_has_buffer.End();
+  if_was_neutered.End();
 
   return Pop();
 }
@@ -9726,6 +9718,45 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
 }
 
 
+HValue* HGraphBuilder::BuildAllocateEmptyArrayBuffer(HValue* byte_length) {
+  HAllocate* result =
+      BuildAllocate(Add<HConstant>(JSArrayBuffer::kSizeWithInternalFields),
+                    HType::JSObject(), JS_ARRAY_BUFFER_TYPE, HAllocationMode());
+
+  HValue* global_object = Add<HLoadNamedField>(
+      context(), nullptr,
+      HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
+  HValue* native_context = Add<HLoadNamedField>(
+      global_object, nullptr, HObjectAccess::ForGlobalObjectNativeContext());
+  Add<HStoreNamedField>(
+      result, HObjectAccess::ForMap(),
+      Add<HLoadNamedField>(
+          native_context, nullptr,
+          HObjectAccess::ForContextSlot(Context::ARRAY_BUFFER_MAP_INDEX)));
+
+  Add<HStoreNamedField>(result, HObjectAccess::ForJSArrayBufferBackingStore(),
+                        Add<HConstant>(ExternalReference()));
+  Add<HStoreNamedField>(result, HObjectAccess::ForJSArrayBufferByteLength(),
+                        byte_length);
+  Add<HStoreNamedField>(result, HObjectAccess::ForJSArrayBufferBitFieldSlot(),
+                        graph()->GetConstant0());
+  Add<HStoreNamedField>(
+      result, HObjectAccess::ForJSArrayBufferBitField(),
+      Add<HConstant>((1 << JSArrayBuffer::IsExternal::kShift) |
+                     (1 << JSArrayBuffer::IsNeuterable::kShift)));
+
+  for (int field = 0; field < v8::ArrayBuffer::kInternalFieldCount; ++field) {
+    Add<HStoreNamedField>(
+        result,
+        HObjectAccess::ForObservableJSObjectOffset(
+            JSArrayBuffer::kSize + field * kPointerSize, Representation::Smi()),
+        graph()->GetConstant0());
+  }
+
+  return result;
+}
+
+
 template <class ViewClass>
 void HGraphBuilder::BuildArrayBufferViewInitialization(
     HValue* obj,
@@ -9749,17 +9780,8 @@ void HGraphBuilder::BuildArrayBufferViewInitialization(
       obj,
       HObjectAccess::ForJSArrayBufferViewByteLength(),
       byte_length);
-
-  if (buffer != NULL) {
-    Add<HStoreNamedField>(
-        obj,
-        HObjectAccess::ForJSArrayBufferViewBuffer(), buffer);
-  } else {
-    Add<HStoreNamedField>(
-        obj,
-        HObjectAccess::ForJSArrayBufferViewBuffer(),
-        Add<HConstant>(static_cast<int32_t>(0)));
-  }
+  Add<HStoreNamedField>(obj, HObjectAccess::ForJSArrayBufferViewBuffer(),
+                        buffer);
 }
 
 
@@ -9981,8 +10003,12 @@ void HOptimizedGraphBuilder::GenerateTypedArrayInitialize(
 
 
   { //  byte_offset is Smi.
-    BuildArrayBufferViewInitialization<JSTypedArray>(
-        obj, buffer, byte_offset, byte_length);
+    HValue* allocated_buffer = buffer;
+    if (buffer == NULL) {
+      allocated_buffer = BuildAllocateEmptyArrayBuffer(byte_length);
+    }
+    BuildArrayBufferViewInitialization<JSTypedArray>(obj, allocated_buffer,
+                                                     byte_offset, byte_length);
 
 
     HInstruction* length = AddUncasted<HDiv>(byte_length,
index e229b04..f5fa62f 100644 (file)
@@ -1899,6 +1899,7 @@ class HGraphBuilder {
   SourcePosition source_position() { return position_; }
   void set_source_position(SourcePosition position) { position_ = position; }
 
+  HValue* BuildAllocateEmptyArrayBuffer(HValue* byte_length);
   template <typename ViewClass>
   void BuildArrayBufferViewInitialization(HValue* obj,
                                           HValue* buffer,
index d4b8b61..f28afa8 100644 (file)
@@ -4978,14 +4978,10 @@ void LCodeGen::DoCheckArrayBufferNotNeutered(
   Register view = ToRegister(instr->view());
   Register scratch = ToRegister(instr->scratch());
 
-  Label has_no_buffer;
   __ mov(scratch, FieldOperand(view, JSArrayBufferView::kBufferOffset));
-  __ JumpIfSmi(scratch, &has_no_buffer);
   __ test_b(FieldOperand(scratch, JSArrayBuffer::kBitFieldOffset),
             1 << JSArrayBuffer::WasNeutered::kShift);
   DeoptimizeIf(not_zero, instr, Deoptimizer::kOutOfBounds);
-
-  __ bind(&has_no_buffer);
 }
 
 
index 8100ae1..2abde16 100644 (file)
@@ -5173,14 +5173,10 @@ void LCodeGen::DoCheckArrayBufferNotNeutered(
   Register view = ToRegister(instr->view());
   Register scratch = scratch0();
 
-  Label has_no_buffer;
   __ lw(scratch, FieldMemOperand(view, JSArrayBufferView::kBufferOffset));
-  __ JumpIfSmi(scratch, &has_no_buffer);
   __ lw(scratch, FieldMemOperand(scratch, JSArrayBuffer::kBitFieldOffset));
   __ And(at, scratch, 1 << JSArrayBuffer::WasNeutered::kShift);
   DeoptimizeIf(ne, instr, Deoptimizer::kOutOfBounds, at, Operand(zero_reg));
-
-  __ bind(&has_no_buffer);
 }
 
 
index 340f57b..58ea58c 100644 (file)
@@ -5233,14 +5233,10 @@ void LCodeGen::DoCheckArrayBufferNotNeutered(
   Register view = ToRegister(instr->view());
   Register scratch = scratch0();
 
-  Label has_no_buffer;
   __ ld(scratch, FieldMemOperand(view, JSArrayBufferView::kBufferOffset));
-  __ JumpIfSmi(scratch, &has_no_buffer);
   __ lw(scratch, FieldMemOperand(scratch, JSArrayBuffer::kBitFieldOffset));
   __ And(at, scratch, 1 << JSArrayBuffer::WasNeutered::kShift);
   DeoptimizeIf(ne, instr, Deoptimizer::kOutOfBounds, at, Operand(zero_reg));
-
-  __ bind(&has_no_buffer);
 }
 
 
index c0be396..4fde394 100644 (file)
@@ -6508,7 +6508,7 @@ ACCESSORS(JSArrayBufferView, raw_byte_length, Object, kByteLengthOffset)
 
 
 bool JSArrayBufferView::WasNeutered() const {
-  return !buffer()->IsSmi() && JSArrayBuffer::cast(buffer())->was_neutered();
+  return JSArrayBuffer::cast(buffer())->was_neutered();
 }
 
 
index 6798d0f..002c3c2 100644 (file)
@@ -17076,11 +17076,18 @@ Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
           map,
           FixedToExternalElementsKind(map->elements_kind()));
 
-  Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
   Handle<FixedTypedArrayBase> fixed_typed_array(
       FixedTypedArrayBase::cast(typed_array->elements()));
-  Runtime::SetupArrayBufferAllocatingData(isolate, buffer,
-      fixed_typed_array->DataSize(), false);
+
+  Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(typed_array->buffer()),
+                               isolate);
+  void* backing_store =
+      isolate->array_buffer_allocator()->AllocateUninitialized(
+          fixed_typed_array->DataSize());
+  isolate->heap()->RegisterNewArrayBuffer(backing_store,
+                                          fixed_typed_array->DataSize());
+  buffer->set_backing_store(backing_store);
+  buffer->set_is_external(false);
   memcpy(buffer->backing_store(),
          fixed_typed_array->DataPtr(),
          fixed_typed_array->DataSize());
@@ -17089,7 +17096,6 @@ Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
           fixed_typed_array->length(), typed_array->type(),
           static_cast<uint8_t*>(buffer->backing_store()));
 
-  typed_array->set_buffer(*buffer);
   JSObject::SetMapAndElements(typed_array, new_map, new_elements);
 
   return buffer;
@@ -17097,9 +17103,8 @@ Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
 
 
 Handle<JSArrayBuffer> JSTypedArray::GetBuffer() {
-  Handle<Object> result(buffer(), GetIsolate());
-  if (*result != Smi::FromInt(0)) {
-    DCHECK(IsExternalArrayElementsKind(map()->elements_kind()));
+  if (IsExternalArrayElementsKind(map()->elements_kind())) {
+    Handle<Object> result(buffer(), GetIsolate());
     return Handle<JSArrayBuffer>::cast(result);
   }
   Handle<JSTypedArray> self(this);
index 6ef5b58..50dcd19 100644 (file)
@@ -5430,14 +5430,10 @@ void LCodeGen::DoCheckArrayBufferNotNeutered(
   Register view = ToRegister(instr->view());
   Register scratch = scratch0();
 
-  Label has_no_buffer;
   __ LoadP(scratch, FieldMemOperand(view, JSArrayBufferView::kBufferOffset));
-  __ JumpIfSmi(scratch, &has_no_buffer);
   __ lwz(scratch, FieldMemOperand(scratch, JSArrayBuffer::kBitFieldOffset));
   __ andi(r0, scratch, Operand(1 << JSArrayBuffer::WasNeutered::kShift));
   DeoptimizeIf(ne, instr, Deoptimizer::kOutOfBounds, cr0);
-
-  __ bind(&has_no_buffer);
 }
 
 
index b95d20f..93ff56d 100644 (file)
@@ -241,7 +241,9 @@ RUNTIME_FUNCTION(Runtime_TypedArrayInitialize) {
     JSObject::SetMapAndElements(holder, map, elements);
     DCHECK(IsExternalArrayElementsKind(holder->map()->elements_kind()));
   } else {
-    holder->set_buffer(Smi::FromInt(0));
+    Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
+    Runtime::SetupArrayBuffer(isolate, buffer, true, NULL, byte_length);
+    holder->set_buffer(*buffer);
     Handle<FixedTypedArrayBase> elements =
         isolate->factory()->NewFixedTypedArray(static_cast<int>(length),
                                                array_type);
index b095119..e70bebd 100644 (file)
@@ -5165,15 +5165,11 @@ void LCodeGen::DoCheckArrayBufferNotNeutered(
     LCheckArrayBufferNotNeutered* instr) {
   Register view = ToRegister(instr->view());
 
-  Label has_no_buffer;
   __ movp(kScratchRegister,
           FieldOperand(view, JSArrayBufferView::kBufferOffset));
-  __ JumpIfSmi(kScratchRegister, &has_no_buffer);
   __ testb(FieldOperand(kScratchRegister, JSArrayBuffer::kBitFieldOffset),
            Immediate(1 << JSArrayBuffer::WasNeutered::kShift));
   DeoptimizeIf(not_zero, instr, Deoptimizer::kOutOfBounds);
-
-  __ bind(&has_no_buffer);
 }
 
 
index fd2d3bb..af118d5 100644 (file)
@@ -5497,14 +5497,10 @@ void LCodeGen::DoCheckArrayBufferNotNeutered(
   Register view = ToRegister(instr->view());
   Register scratch = ToRegister(instr->scratch());
 
-  Label has_no_buffer;
   __ mov(scratch, FieldOperand(view, JSArrayBufferView::kBufferOffset));
-  __ JumpIfSmi(scratch, &has_no_buffer);
   __ test_b(FieldOperand(scratch, JSArrayBuffer::kBitFieldOffset),
             1 << JSArrayBuffer::WasNeutered::kShift);
   DeoptimizeIf(not_zero, instr, Deoptimizer::kOutOfBounds);
-
-  __ bind(&has_no_buffer);
 }