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;
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);
}
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;
}
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);
}
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);
}
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
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) \
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,
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);
JSArrayBuffer::kBitFieldOffset, Representation::Integer32());
}
+ static HObjectAccess ForJSArrayBufferBitFieldSlot() {
+ return HObjectAccess::ForObservableJSObjectOffset(
+ JSArrayBuffer::kBitFieldSlot, Representation::Smi());
+ }
+
static HObjectAccess ForExternalArrayExternalPointer() {
return HObjectAccess::ForObservableJSObjectOffset(
ExternalArray::kExternalPointerOffset, Representation::External());
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();
}
}
+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,
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);
}
{ // 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,
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,
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);
}
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);
}
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);
}
bool JSArrayBufferView::WasNeutered() const {
- return !buffer()->IsSmi() && JSArrayBuffer::cast(buffer())->was_neutered();
+ return JSArrayBuffer::cast(buffer())->was_neutered();
}
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());
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;
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);
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);
}
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);
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);
}
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);
}