Add HArrayBufferNotNeutered instruction
authorjochen <jochen@chromium.org>
Tue, 28 Apr 2015 13:42:54 +0000 (06:42 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 28 Apr 2015 13:43:03 +0000 (13:43 +0000)
This instruction can be hoisted out of loops even though it contains a branch.

BUG=v8:3996
R=bmeurer@chromium.org
LOG=n

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

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

27 files changed:
src/arm/lithium-arm.cc
src/arm/lithium-arm.h
src/arm/lithium-codegen-arm.cc
src/arm64/lithium-arm64.cc
src/arm64/lithium-arm64.h
src/arm64/lithium-codegen-arm64.cc
src/hydrogen-instructions.cc
src/hydrogen-instructions.h
src/hydrogen.cc
src/ia32/lithium-codegen-ia32.cc
src/ia32/lithium-ia32.cc
src/ia32/lithium-ia32.h
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/ppc/lithium-codegen-ppc.cc
src/ppc/lithium-ppc.cc
src/ppc/lithium-ppc.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

index 6268df3dfcf6ab3d006492456c9986d492fcfc90..7d600db9386e0dd97a99ad28fe37493a82c5955f 100644 (file)
@@ -2046,6 +2046,15 @@ LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
 }
 
 
+LInstruction* LChunkBuilder::DoCheckArrayBufferNotNeutered(
+    HCheckArrayBufferNotNeutered* instr) {
+  LOperand* view = UseRegisterAtStart(instr->value());
+  LCheckArrayBufferNotNeutered* result =
+      new (zone()) LCheckArrayBufferNotNeutered(view);
+  return AssignEnvironment(result);
+}
+
+
 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
   LOperand* value = UseRegisterAtStart(instr->value());
   LInstruction* result = new(zone()) LCheckInstanceType(value);
index 7fca1ee7cb2eaccb48fdd100639daaa60d86c2a4..66df46a3bd184b4d628608dcfa7b1496397dd057 100644 (file)
@@ -37,6 +37,7 @@ class LCodeGen;
   V(CallNewArray)                            \
   V(CallRuntime)                             \
   V(CallStub)                                \
+  V(CheckArrayBufferNotNeutered)             \
   V(CheckInstanceType)                       \
   V(CheckNonSmi)                             \
   V(CheckMaps)                               \
@@ -2375,6 +2376,19 @@ class LCheckValue final : public LTemplateInstruction<0, 1, 0> {
 };
 
 
+class LCheckArrayBufferNotNeutered final
+    : public LTemplateInstruction<0, 1, 0> {
+ public:
+  explicit LCheckArrayBufferNotNeutered(LOperand* view) { inputs_[0] = view; }
+
+  LOperand* view() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered,
+                               "check-array-buffer-not-neutered")
+  DECLARE_HYDROGEN_ACCESSOR(CheckArrayBufferNotNeutered)
+};
+
+
 class LCheckInstanceType final : public LTemplateInstruction<0, 1, 0> {
  public:
   explicit LCheckInstanceType(LOperand* value) {
index 667646474a9f9e4fff164d2703aa56e9dee3e9c9..fc33139cb01b0be2b882728f9f061a8ecc5f44e5 100644 (file)
@@ -5154,6 +5154,22 @@ void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
 }
 
 
+void LCodeGen::DoCheckArrayBufferNotNeutered(
+    LCheckArrayBufferNotNeutered* instr) {
+  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);
+}
+
+
 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
   Register input = ToRegister(instr->value());
   Register scratch = scratch0();
index 2dfcdb08615f6b69ba721d1d50d19c7d82ce332a..a9daec492051e2e0996937ba56c94905e786a6a6 100644 (file)
@@ -1221,6 +1221,15 @@ LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) {
 }
 
 
+LInstruction* LChunkBuilder::DoCheckArrayBufferNotNeutered(
+    HCheckArrayBufferNotNeutered* instr) {
+  LOperand* view = UseRegisterAtStart(instr->value());
+  LCheckArrayBufferNotNeutered* result =
+      new (zone()) LCheckArrayBufferNotNeutered(view);
+  return AssignEnvironment(result);
+}
+
+
 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
   LOperand* value = UseRegisterAtStart(instr->value());
   LOperand* temp = TempRegister();
index 506110c7773b1507bdf71cbff5bc86534d40df0a..af8ef00d100e2b0de0ac43ac62f3ac0f053ee08b 100644 (file)
@@ -40,6 +40,7 @@ class LCodeGen;
   V(CallRuntime)                             \
   V(CallStub)                                \
   V(CallWithDescriptor)                      \
+  V(CheckArrayBufferNotNeutered)             \
   V(CheckInstanceType)                       \
   V(CheckMapValue)                           \
   V(CheckMaps)                               \
@@ -935,6 +936,19 @@ class LCallStub final : public LTemplateInstruction<1, 1, 0> {
 };
 
 
+class LCheckArrayBufferNotNeutered final
+    : public LTemplateInstruction<0, 1, 0> {
+ public:
+  explicit LCheckArrayBufferNotNeutered(LOperand* view) { inputs_[0] = view; }
+
+  LOperand* view() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered,
+                               "check-array-buffer-not-neutered")
+  DECLARE_HYDROGEN_ACCESSOR(CheckArrayBufferNotNeutered)
+};
+
+
 class LCheckInstanceType final : public LTemplateInstruction<0, 1, 1> {
  public:
   explicit LCheckInstanceType(LOperand* value, LOperand* temp) {
index 13da0b99b1fad3d81514f65db56d079c7c6d1480..badd1773748e580f44b3ef3e0ba8dc71de0d4239 100644 (file)
@@ -2229,6 +2229,23 @@ void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
 }
 
 
+void LCodeGen::DoCheckArrayBufferNotNeutered(
+    LCheckArrayBufferNotNeutered* instr) {
+  UseScratchRegisterScope temps(masm());
+  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);
+}
+
+
 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
   Register input = ToRegister(instr->value());
   Register scratch = ToRegister(instr->temp());
index 674096b3049935e24915cd0e57219c0231baeb2e..7956437bd8790d6aa806095712812ca4348120f8 100644 (file)
@@ -854,6 +854,7 @@ bool HInstruction::CanDeoptimize() {
     case HValue::kCallRuntime:
     case HValue::kCallWithDescriptor:
     case HValue::kChange:
+    case HValue::kCheckArrayBufferNotNeutered:
     case HValue::kCheckHeapObject:
     case HValue::kCheckInstanceType:
     case HValue::kCheckMapValue:
index 71fc0f99a1870eebd38d0e8e5015430fd6b367d2..771197d514473b55b9881f7d05dcf7c2c333df5e 100644 (file)
@@ -70,6 +70,7 @@ class LChunkBuilder;
   V(CallStub)                                 \
   V(CapturedObject)                           \
   V(Change)                                   \
+  V(CheckArrayBufferNotNeutered)              \
   V(CheckHeapObject)                          \
   V(CheckInstanceType)                        \
   V(CheckMaps)                                \
@@ -2952,6 +2953,36 @@ class HCheckSmi final : public HUnaryOperation {
 };
 
 
+class HCheckArrayBufferNotNeutered final : public HUnaryOperation {
+ public:
+  DECLARE_INSTRUCTION_FACTORY_P1(HCheckArrayBufferNotNeutered, HValue*);
+
+  bool HasEscapingOperandAt(int index) override { return false; }
+  Representation RequiredInputRepresentation(int index) override {
+    return Representation::Tagged();
+  }
+
+  HType CalculateInferredType() override {
+    if (value()->type().IsHeapObject()) return value()->type();
+    return HType::HeapObject();
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered)
+
+ protected:
+  bool DataEquals(HValue* other) override { return true; }
+  int RedefinedOperandIndex() override { return 0; }
+
+ private:
+  explicit HCheckArrayBufferNotNeutered(HValue* value)
+      : HUnaryOperation(value) {
+    set_representation(Representation::Tagged());
+    SetFlag(kUseGVN);
+    SetDependsOnFlag(kCalls);
+  }
+};
+
+
 class HCheckHeapObject final : public HUnaryOperation {
  public:
   DECLARE_INSTRUCTION_FACTORY_P1(HCheckHeapObject, HValue*);
index adc4aa4d5f8fd235cd86098e620c21d4ddb9787f..937f5b086b41029a1e4c70130ae3953cca3d1fe8 100644 (file)
@@ -2425,6 +2425,8 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
   HValue* checked_key = NULL;
   if (IsExternalArrayElementsKind(elements_kind) ||
       IsFixedTypedArrayElementsKind(elements_kind)) {
+    checked_object = Add<HCheckArrayBufferNotNeutered>(checked_object);
+
     HValue* backing_store;
     if (IsExternalArrayElementsKind(elements_kind)) {
       backing_store = Add<HLoadNamedField>(
@@ -2434,23 +2436,6 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
     }
     if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
       NoObservableSideEffectsScope no_effects(this);
-      if (IsExternalArrayElementsKind(elements_kind)) {
-        HInstruction* buffer =
-            Add<HLoadNamedField>(checked_object, nullptr,
-                                 HObjectAccess::ForJSArrayBufferViewBuffer());
-        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.ThenDeopt(Deoptimizer::kOutOfBounds);
-        if_was_neutered.End();
-      }
       IfBuilder length_checker(this);
       length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT);
       length_checker.Then();
@@ -2465,14 +2450,6 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
       length_checker.End();
       return result;
     } else {
-      if (IsExternalArrayElementsKind(elements_kind)) {
-        HInstruction* buffer =
-            Add<HLoadNamedField>(checked_object, nullptr,
-                                 HObjectAccess::ForJSArrayBufferViewBuffer());
-        HInstruction* buffer_length = Add<HLoadNamedField>(
-            buffer, nullptr, HObjectAccess::ForJSArrayBufferByteLength());
-        Add<HBoundsCheck>(graph()->GetConstant0(), buffer_length);
-      }
       DCHECK(store_mode == STANDARD_STORE);
       checked_key = Add<HBoundsCheck>(key, length);
       return AddElementAccess(
@@ -6340,8 +6317,8 @@ HValue* HOptimizedGraphBuilder::BuildMonomorphicAccess(
 
   if (info->GetJSArrayBufferViewFieldAccess(&access)) {
     DCHECK(info->IsLoad());
-    return BuildArrayBufferViewFieldAccessor(
-        object, checked_object, FieldIndex::ForInObjectOffset(access.offset()));
+    checked_object = Add<HCheckArrayBufferNotNeutered>(checked_object);
+    return New<HLoadNamedField>(object, checked_object, access);
   }
 
   if (info->name().is_identical_to(isolate()->factory()->prototype_string()) &&
index 5af19d01ef4d5592c2498c92001d805b1e68ac59..d4b8b6186d677e50e8fd1098a1e944421b2a7e1e 100644 (file)
@@ -4973,6 +4973,22 @@ void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
 }
 
 
+void LCodeGen::DoCheckArrayBufferNotNeutered(
+    LCheckArrayBufferNotNeutered* instr) {
+  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);
+}
+
+
 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
   Register input = ToRegister(instr->value());
   Register temp = ToRegister(instr->temp());
index 6ff14315517478155584752ad6abcb51f264ae9c..d9cef76afff441d592ad5a698aca53204f2868eb 100644 (file)
@@ -2030,6 +2030,16 @@ LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
 }
 
 
+LInstruction* LChunkBuilder::DoCheckArrayBufferNotNeutered(
+    HCheckArrayBufferNotNeutered* instr) {
+  LOperand* view = UseRegisterAtStart(instr->value());
+  LOperand* scratch = TempRegister();
+  LCheckArrayBufferNotNeutered* result =
+      new (zone()) LCheckArrayBufferNotNeutered(view, scratch);
+  return AssignEnvironment(result);
+}
+
+
 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
   LOperand* value = UseRegisterAtStart(instr->value());
   LOperand* temp = TempRegister();
index f40df09fb2213233a1325f41831a99a43f30a7fd..d64d3626d54dbd5524e86e623fb2ede1f79646b1 100644 (file)
@@ -41,6 +41,7 @@ class LCodeGen;
   V(CallNewArray)                            \
   V(CallRuntime)                             \
   V(CallStub)                                \
+  V(CheckArrayBufferNotNeutered)             \
   V(CheckInstanceType)                       \
   V(CheckMaps)                               \
   V(CheckMapValue)                           \
@@ -2377,6 +2378,23 @@ class LCheckValue final : public LTemplateInstruction<0, 1, 0> {
 };
 
 
+class LCheckArrayBufferNotNeutered final
+    : public LTemplateInstruction<0, 1, 1> {
+ public:
+  explicit LCheckArrayBufferNotNeutered(LOperand* view, LOperand* scratch) {
+    inputs_[0] = view;
+    temps_[0] = scratch;
+  }
+
+  LOperand* view() { return inputs_[0]; }
+  LOperand* scratch() { return temps_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered,
+                               "check-array-buffer-not-neutered")
+  DECLARE_HYDROGEN_ACCESSOR(CheckArrayBufferNotNeutered)
+};
+
+
 class LCheckInstanceType final : public LTemplateInstruction<0, 1, 1> {
  public:
   LCheckInstanceType(LOperand* value, LOperand* temp) {
index 4e1cd8140b859d40bd92f7981de5b9d0d05a04b3..0ba5e23ce984b6f2da9be285caa070cac734d7ee 100644 (file)
@@ -5168,6 +5168,22 @@ void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
 }
 
 
+void LCodeGen::DoCheckArrayBufferNotNeutered(
+    LCheckArrayBufferNotNeutered* instr) {
+  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);
+
+  __ bind(&has_no_buffer);
+}
+
+
 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
   Register input = ToRegister(instr->value());
   Register scratch = scratch0();
index 578db3b3184559d448e758036483bb086b88bec0..c2d22ea2c085580ee135e447f204c971b2136003 100644 (file)
@@ -1993,6 +1993,15 @@ LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
 }
 
 
+LInstruction* LChunkBuilder::DoCheckArrayBufferNotNeutered(
+    HCheckArrayBufferNotNeutered* instr) {
+  LOperand* view = UseRegisterAtStart(instr->value());
+  LCheckArrayBufferNotNeutered* result =
+      new (zone()) LCheckArrayBufferNotNeutered(view);
+  return AssignEnvironment(result);
+}
+
+
 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
   LOperand* value = UseRegisterAtStart(instr->value());
   LInstruction* result = new(zone()) LCheckInstanceType(value);
index c5d2eb28cea5072950a159c000c7980debb75c2c..b2ab1a058fd7264069b99f71887ae37785cb970d 100644 (file)
@@ -37,6 +37,7 @@ class LCodeGen;
   V(CallNewArray)                            \
   V(CallRuntime)                             \
   V(CallStub)                                \
+  V(CheckArrayBufferNotNeutered)             \
   V(CheckInstanceType)                       \
   V(CheckMaps)                               \
   V(CheckMapValue)                           \
@@ -2332,6 +2333,19 @@ class LCheckValue final : public LTemplateInstruction<0, 1, 0> {
 };
 
 
+class LCheckArrayBufferNotNeutered final
+    : public LTemplateInstruction<0, 1, 0> {
+ public:
+  explicit LCheckArrayBufferNotNeutered(LOperand* view) { inputs_[0] = view; }
+
+  LOperand* view() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered,
+                               "check-array-buffer-not-neutered")
+  DECLARE_HYDROGEN_ACCESSOR(CheckArrayBufferNotNeutered)
+};
+
+
 class LCheckInstanceType final : public LTemplateInstruction<0, 1, 0> {
  public:
   explicit LCheckInstanceType(LOperand* value) {
index c7dd637c24a4e708b9178a5bb85f5d54a5dd032b..bf3119d080aa752f9497be9aa864495d7739ca88 100644 (file)
@@ -5228,6 +5228,22 @@ void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
 }
 
 
+void LCodeGen::DoCheckArrayBufferNotNeutered(
+    LCheckArrayBufferNotNeutered* instr) {
+  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);
+
+  __ bind(&has_no_buffer);
+}
+
+
 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
   Register input = ToRegister(instr->value());
   Register scratch = scratch0();
index ee32dcef4ebb84c8ae4672759004308ff61d924f..7495b747705ead03af4a292341718ab205cc7b0f 100644 (file)
@@ -1991,6 +1991,15 @@ LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
 }
 
 
+LInstruction* LChunkBuilder::DoCheckArrayBufferNotNeutered(
+    HCheckArrayBufferNotNeutered* instr) {
+  LOperand* view = UseRegisterAtStart(instr->value());
+  LCheckArrayBufferNotNeutered* result =
+      new (zone()) LCheckArrayBufferNotNeutered(view);
+  return AssignEnvironment(result);
+}
+
+
 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
   LOperand* value = UseRegisterAtStart(instr->value());
   LInstruction* result = new(zone()) LCheckInstanceType(value);
index 0aa66776a3c71a92a0e7d6ad0c571a7b968ad4cd..3805fb90a72c45cfa07dad6663ac595907bd3e43 100644 (file)
@@ -37,6 +37,7 @@ class LCodeGen;
   V(CallNewArray)                            \
   V(CallRuntime)                             \
   V(CallStub)                                \
+  V(CheckArrayBufferNotNeutered)             \
   V(CheckInstanceType)                       \
   V(CheckMaps)                               \
   V(CheckMapValue)                           \
@@ -2314,6 +2315,19 @@ class LCheckValue final : public LTemplateInstruction<0, 1, 0> {
 };
 
 
+class LCheckArrayBufferNotNeutered final
+    : public LTemplateInstruction<0, 1, 0> {
+ public:
+  explicit LCheckArrayBufferNotNeutered(LOperand* view) { inputs_[0] = view; }
+
+  LOperand* view() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered,
+                               "check-array-buffer-not-neutered")
+  DECLARE_HYDROGEN_ACCESSOR(CheckArrayBufferNotNeutered)
+};
+
+
 class LCheckInstanceType final : public LTemplateInstruction<0, 1, 0> {
  public:
   explicit LCheckInstanceType(LOperand* value) {
index ae58f31ea396c75a16e3016dc574690b29861c19..c34718bad5b86b04cb897174a1936ca973de3eaa 100644 (file)
@@ -5425,6 +5425,22 @@ void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
 }
 
 
+void LCodeGen::DoCheckArrayBufferNotNeutered(
+    LCheckArrayBufferNotNeutered* instr) {
+  Register view = ToRegister(instr->view());
+  Register scratch = scratch0();
+
+  Label has_no_buffer;
+  __ LoadP(scratch, FieldMemOperand(view, JSArrayBufferView::kBufferOffset));
+  __ JumpIfSmi(scratch, &has_no_buffer);
+  __ LoadP(scratch, FieldMemOperand(scratch, JSArrayBuffer::kBitFieldOffset));
+  __ andi(r0, scratch, Operand(1 << JSArrayBuffer::WasNeutered::kShift));
+  DeoptimizeIf(ne, instr, Deoptimizer::kOutOfBounds);
+
+  __ bind(&has_no_buffer);
+}
+
+
 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
   Register input = ToRegister(instr->value());
   Register scratch = scratch0();
index 81eb3fd6e47a957e15e72379988e340e668b6bb1..fd2cc44cec08aaebfa8aa094f146e08c017acecf 100644 (file)
@@ -2006,6 +2006,15 @@ LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
 }
 
 
+LInstruction* LChunkBuilder::DoCheckArrayBufferNotNeutered(
+    HCheckArrayBufferNotNeutered* instr) {
+  LOperand* view = UseRegisterAtStart(instr->value());
+  LCheckArrayBufferNotNeutered* result =
+      new (zone()) LCheckArrayBufferNotNeutered(view);
+  return AssignEnvironment(result);
+}
+
+
 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
   LOperand* value = UseRegisterAtStart(instr->value());
   LInstruction* result = new (zone()) LCheckInstanceType(value);
index 63c70992c19774965d5d02dc9bfd42061e00d0c2..052e60c2939fc7d897250e17cc047aed0315249f 100644 (file)
@@ -37,6 +37,7 @@ class LCodeGen;
   V(CallNewArray)                            \
   V(CallRuntime)                             \
   V(CallStub)                                \
+  V(CheckArrayBufferNotNeutered)             \
   V(CheckInstanceType)                       \
   V(CheckNonSmi)                             \
   V(CheckMaps)                               \
@@ -2279,6 +2280,19 @@ class LCheckValue final : public LTemplateInstruction<0, 1, 0> {
 };
 
 
+class LCheckArrayBufferNotNeutered final
+    : public LTemplateInstruction<0, 1, 0> {
+ public:
+  explicit LCheckArrayBufferNotNeutered(LOperand* view) { inputs_[0] = view; }
+
+  LOperand* view() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered,
+                               "check-array-buffer-not-neutered")
+  DECLARE_HYDROGEN_ACCESSOR(CheckArrayBufferNotNeutered)
+};
+
+
 class LCheckInstanceType final : public LTemplateInstruction<0, 1, 0> {
  public:
   explicit LCheckInstanceType(LOperand* value) { inputs_[0] = value; }
index 7c1668f1fa11a0334beb6891e91582a365ab7615..b095119a53643c08010d91a4af50b7dfb5a6d6d8 100644 (file)
@@ -5161,6 +5161,22 @@ void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
 }
 
 
+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);
+}
+
+
 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
   Register input = ToRegister(instr->value());
 
index 6cffc1c1ecb2ef6a8219f69c5397f8cc9059ee6f..80f9f0b49af0866250f99424541de692356ff2d7 100644 (file)
@@ -1991,6 +1991,15 @@ LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
 }
 
 
+LInstruction* LChunkBuilder::DoCheckArrayBufferNotNeutered(
+    HCheckArrayBufferNotNeutered* instr) {
+  LOperand* view = UseRegisterAtStart(instr->value());
+  LCheckArrayBufferNotNeutered* result =
+      new (zone()) LCheckArrayBufferNotNeutered(view);
+  return AssignEnvironment(result);
+}
+
+
 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
   LOperand* value = UseRegisterAtStart(instr->value());
   LCheckInstanceType* result = new(zone()) LCheckInstanceType(value);
index cddaa885bf473425ede5c948aee2b28112a39869..be5941c2a2dd6f1e4d163e532e1201a431f7722a 100644 (file)
@@ -37,6 +37,7 @@ class LCodeGen;
   V(CallNewArray)                            \
   V(CallRuntime)                             \
   V(CallStub)                                \
+  V(CheckArrayBufferNotNeutered)             \
   V(CheckInstanceType)                       \
   V(CheckMaps)                               \
   V(CheckMapValue)                           \
@@ -2351,6 +2352,19 @@ class LCheckValue final : public LTemplateInstruction<0, 1, 0> {
 };
 
 
+class LCheckArrayBufferNotNeutered final
+    : public LTemplateInstruction<0, 1, 0> {
+ public:
+  explicit LCheckArrayBufferNotNeutered(LOperand* view) { inputs_[0] = view; }
+
+  LOperand* view() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered,
+                               "check-array-buffer-not-neutered")
+  DECLARE_HYDROGEN_ACCESSOR(CheckArrayBufferNotNeutered)
+};
+
+
 class LCheckInstanceType final : public LTemplateInstruction<0, 1, 0> {
  public:
   explicit LCheckInstanceType(LOperand* value) {
index 13dfc17345f028d757d61387854e54aed7deee8f..62bb19087331b7d142a93a1e93469d050771176f 100644 (file)
@@ -5476,6 +5476,22 @@ void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
 }
 
 
+void LCodeGen::DoCheckArrayBufferNotNeutered(
+    LCheckArrayBufferNotNeutered* instr) {
+  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);
+}
+
+
 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
   Register input = ToRegister(instr->value());
   Register temp = ToRegister(instr->temp());
index 0bf162c2533222c0ee0b47d507fe00f423438862..a1bf2f1e64f99b92bb5138fac8ec0e38e00c8461 100644 (file)
@@ -2031,6 +2031,16 @@ LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
 }
 
 
+LInstruction* LChunkBuilder::DoCheckArrayBufferNotNeutered(
+    HCheckArrayBufferNotNeutered* instr) {
+  LOperand* view = UseRegisterAtStart(instr->value());
+  LOperand* scratch = TempRegister();
+  LCheckArrayBufferNotNeutered* result =
+      new (zone()) LCheckArrayBufferNotNeutered(view, scratch);
+  return AssignEnvironment(result);
+}
+
+
 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
   LOperand* value = UseRegisterAtStart(instr->value());
   LOperand* temp = TempRegister();
index 6cc89b1fba969dab33efdca9c938184262ed9e61..7a8b1e7d8098bd37156808ec107975fc6072bfb1 100644 (file)
@@ -41,6 +41,7 @@ class LCodeGen;
   V(CallNewArray)                            \
   V(CallRuntime)                             \
   V(CallStub)                                \
+  V(CheckArrayBufferNotNeutered)             \
   V(CheckInstanceType)                       \
   V(CheckMaps)                               \
   V(CheckMapValue)                           \
@@ -2381,6 +2382,23 @@ class LCheckValue final : public LTemplateInstruction<0, 1, 0> {
 };
 
 
+class LCheckArrayBufferNotNeutered final
+    : public LTemplateInstruction<0, 1, 1> {
+ public:
+  explicit LCheckArrayBufferNotNeutered(LOperand* view, LOperand* scratch) {
+    inputs_[0] = view;
+    temps_[0] = scratch;
+  }
+
+  LOperand* view() { return inputs_[0]; }
+  LOperand* scratch() { return temps_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CheckArrayBufferNotNeutered,
+                               "check-array-buffer-not-neutered")
+  DECLARE_HYDROGEN_ACCESSOR(CheckArrayBufferNotNeutered)
+};
+
+
 class LCheckInstanceType final : public LTemplateInstruction<0, 1, 1> {
  public:
   LCheckInstanceType(LOperand* value, LOperand* temp) {