Commit cb21144b authored by bmeurer's avatar bmeurer Committed by Commit bot

[es6] Unify ArrayBuffer and SharedArrayBuffer constructors.

Unify the constructors and isView methods for ArrayBuffer and
SharedArrayBuffer, moving them to C++ because there's no point
in having the JavaScript wrappers for them.

We choose to deliberately violate the ES2015 specification and
implement the ArrayBuffer constructor in a way that matches
Firefox and Safari instead.

CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel
BUG=chromium:565917, v8:4592
TBR=hpayer@chromium.org
R=cbruni@chromium.org
LOG=n

Committed: https://crrev.com/3235ccbb7826ceec2188f6ebab98fc851b54f60e
Cr-Commit-Position: refs/heads/master@{#32590}

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

Cr-Commit-Position: refs/heads/master@{#33072}
parent 66b0d031
...@@ -205,6 +205,8 @@ class Genesis BASE_EMBEDDED { ...@@ -205,6 +205,8 @@ class Genesis BASE_EMBEDDED {
DECLARE_FEATURE_INITIALIZATION(promise_extra, "") DECLARE_FEATURE_INITIALIZATION(promise_extra, "")
#undef DECLARE_FEATURE_INITIALIZATION #undef DECLARE_FEATURE_INITIALIZATION
Handle<JSFunction> InstallArrayBuffer(Handle<JSObject> target,
const char* name);
Handle<JSFunction> InstallInternalArray(Handle<JSObject> target, Handle<JSFunction> InstallInternalArray(Handle<JSObject> target,
const char* name, const char* name,
ElementsKind elements_kind); ElementsKind elements_kind);
...@@ -1345,11 +1347,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object, ...@@ -1345,11 +1347,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
{ // -- A r r a y B u f f e r { // -- A r r a y B u f f e r
Handle<JSFunction> array_buffer_fun = Handle<JSFunction> array_buffer_fun =
InstallFunction( InstallArrayBuffer(global, "ArrayBuffer");
global, "ArrayBuffer", JS_ARRAY_BUFFER_TYPE,
JSArrayBuffer::kSizeWithInternalFields,
isolate->initial_object_prototype(),
Builtins::kIllegal);
InstallWithIntrinsicDefaultProto(isolate, array_buffer_fun, InstallWithIntrinsicDefaultProto(isolate, array_buffer_fun,
Context::ARRAY_BUFFER_FUN_INDEX); Context::ARRAY_BUFFER_FUN_INDEX);
} }
...@@ -2237,13 +2235,9 @@ void Genesis::InitializeGlobal_harmony_reflect() { ...@@ -2237,13 +2235,9 @@ void Genesis::InitializeGlobal_harmony_reflect() {
void Genesis::InitializeGlobal_harmony_sharedarraybuffer() { void Genesis::InitializeGlobal_harmony_sharedarraybuffer() {
if (!FLAG_harmony_sharedarraybuffer) return; if (!FLAG_harmony_sharedarraybuffer) return;
Handle<JSGlobalObject> global( Handle<JSGlobalObject> global(native_context()->global_object());
JSGlobalObject::cast(native_context()->global_object())); Handle<JSFunction> shared_array_buffer_fun =
InstallArrayBuffer(global, "SharedArrayBuffer");
Handle<JSFunction> shared_array_buffer_fun = InstallFunction(
global, "SharedArrayBuffer", JS_ARRAY_BUFFER_TYPE,
JSArrayBuffer::kSizeWithInternalFields,
isolate()->initial_object_prototype(), Builtins::kIllegal);
native_context()->set_shared_array_buffer_fun(*shared_array_buffer_fun); native_context()->set_shared_array_buffer_fun(*shared_array_buffer_fun);
} }
...@@ -2335,6 +2329,36 @@ void Genesis::InitializeGlobal_harmony_proxies() { ...@@ -2335,6 +2329,36 @@ void Genesis::InitializeGlobal_harmony_proxies() {
} }
Handle<JSFunction> Genesis::InstallArrayBuffer(Handle<JSObject> target,
const char* name) {
// Setup the {prototype} with the given {name} for @@toStringTag.
Handle<JSObject> prototype =
factory()->NewJSObject(isolate()->object_function(), TENURED);
JSObject::AddProperty(prototype, factory()->to_string_tag_symbol(),
factory()->NewStringFromAsciiChecked(name),
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
// Allocate the constructor with the given {prototype}.
Handle<JSFunction> array_buffer_fun =
InstallFunction(target, name, JS_ARRAY_BUFFER_TYPE,
JSArrayBuffer::kSizeWithInternalFields, prototype,
Builtins::kArrayBufferConstructor);
array_buffer_fun->shared()->set_construct_stub(
*isolate()->builtins()->ArrayBufferConstructor_ConstructStub());
array_buffer_fun->shared()->DontAdaptArguments();
array_buffer_fun->shared()->set_length(1);
// Install the "constructor" property on the {prototype}.
JSObject::AddProperty(prototype, factory()->constructor_string(),
array_buffer_fun, DONT_ENUM);
SimpleInstallFunction(array_buffer_fun, factory()->isView_string(),
Builtins::kArrayBufferIsView, 1, true);
return array_buffer_fun;
}
Handle<JSFunction> Genesis::InstallInternalArray(Handle<JSObject> target, Handle<JSFunction> Genesis::InstallInternalArray(Handle<JSObject> target,
const char* name, const char* name,
ElementsKind elements_kind) { ElementsKind elements_kind) {
......
...@@ -2129,6 +2129,66 @@ BUILTIN(ObjectProtoToString) { ...@@ -2129,6 +2129,66 @@ BUILTIN(ObjectProtoToString) {
} }
// ES6 section 24.1.2.1 ArrayBuffer ( length ) for the [[Call]] case.
BUILTIN(ArrayBufferConstructor) {
HandleScope scope(isolate);
Handle<JSFunction> target = args.target();
DCHECK(*target == target->native_context()->array_buffer_fun() ||
*target == target->native_context()->shared_array_buffer_fun());
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kConstructorNotFunction,
handle(target->shared()->name(), isolate)));
}
// ES6 section 24.1.2.1 ArrayBuffer ( length ) for the [[Construct]] case.
BUILTIN(ArrayBufferConstructor_ConstructStub) {
HandleScope scope(isolate);
Handle<JSFunction> target = args.target();
Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
Handle<Object> length = args.atOrUndefined(isolate, 1);
DCHECK(*target == target->native_context()->array_buffer_fun() ||
*target == target->native_context()->shared_array_buffer_fun());
Handle<Object> number_length;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_length,
Object::ToInteger(isolate, length));
if (number_length->Number() < 0.0) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
}
Handle<Map> initial_map;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, initial_map,
JSFunction::GetDerivedMap(isolate, target, new_target));
size_t byte_length;
if (!TryNumberToSize(isolate, *number_length, &byte_length)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
}
Handle<JSArrayBuffer> result = Handle<JSArrayBuffer>::cast(
isolate->factory()->NewJSObjectFromMap(initial_map));
SharedFlag shared_flag =
(*target == target->native_context()->array_buffer_fun())
? SharedFlag::kNotShared
: SharedFlag::kShared;
if (!JSArrayBuffer::SetupAllocatingData(result, isolate, byte_length, true,
shared_flag)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewRangeError(MessageTemplate::kArrayBufferAllocationFailed));
}
return *result;
}
// ES6 section 24.1.3.1 ArrayBuffer.isView ( arg )
BUILTIN(ArrayBufferIsView) {
SealHandleScope shs(isolate);
DCHECK_EQ(2, args.length());
Object* arg = args[1];
return isolate->heap()->ToBoolean(arg->IsJSArrayBufferView());
}
// ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Call]] case. // ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Call]] case.
BUILTIN(ProxyConstructor) { BUILTIN(ProxyConstructor) {
HandleScope scope(isolate); HandleScope scope(isolate);
......
...@@ -51,58 +51,62 @@ inline bool operator&(BuiltinExtraArguments lhs, BuiltinExtraArguments rhs) { ...@@ -51,58 +51,62 @@ inline bool operator&(BuiltinExtraArguments lhs, BuiltinExtraArguments rhs) {
// Define list of builtins implemented in C++. // Define list of builtins implemented in C++.
#define BUILTIN_LIST_C(V) \ #define BUILTIN_LIST_C(V) \
V(Illegal, kNone) \ V(Illegal, kNone) \
\ \
V(EmptyFunction, kNone) \ V(EmptyFunction, kNone) \
\ \
V(ArrayConcat, kNone) \ V(ArrayConcat, kNone) \
V(ArrayIsArray, kNone) \ V(ArrayIsArray, kNone) \
V(ArrayPop, kNone) \ V(ArrayPop, kNone) \
V(ArrayPush, kNone) \ V(ArrayPush, kNone) \
V(ArrayShift, kNone) \ V(ArrayShift, kNone) \
V(ArraySlice, kNone) \ V(ArraySlice, kNone) \
V(ArraySplice, kNone) \ V(ArraySplice, kNone) \
V(ArrayUnshift, kNone) \ V(ArrayUnshift, kNone) \
\ \
V(DateToPrimitive, kNone) \ V(ArrayBufferConstructor, kTarget) \
\ V(ArrayBufferConstructor_ConstructStub, kTargetAndNewTarget) \
V(FunctionConstructor, kTargetAndNewTarget) \ V(ArrayBufferIsView, kNone) \
V(FunctionPrototypeBind, kNone) \ \
V(FunctionPrototypeToString, kNone) \ V(DateToPrimitive, kNone) \
\ \
V(GeneratorFunctionConstructor, kTargetAndNewTarget) \ V(FunctionConstructor, kTargetAndNewTarget) \
\ V(FunctionPrototypeBind, kNone) \
V(GlobalEval, kTarget) \ V(FunctionPrototypeToString, kNone) \
\ \
V(ObjectAssign, kNone) \ V(GeneratorFunctionConstructor, kTargetAndNewTarget) \
V(ObjectCreate, kNone) \ \
V(ObjectProtoToString, kNone) \ V(GlobalEval, kTarget) \
\ \
V(ProxyConstructor, kNone) \ V(ObjectAssign, kNone) \
V(ProxyConstructor_ConstructStub, kTarget) \ V(ObjectCreate, kNone) \
\ V(ObjectProtoToString, kNone) \
V(ReflectDefineProperty, kNone) \ \
V(ReflectDeleteProperty, kNone) \ V(ProxyConstructor, kNone) \
V(ReflectGet, kNone) \ V(ProxyConstructor_ConstructStub, kTarget) \
V(ReflectGetOwnPropertyDescriptor, kNone) \ \
V(ReflectGetPrototypeOf, kNone) \ V(ReflectDefineProperty, kNone) \
V(ReflectHas, kNone) \ V(ReflectDeleteProperty, kNone) \
V(ReflectIsExtensible, kNone) \ V(ReflectGet, kNone) \
V(ReflectOwnKeys, kNone) \ V(ReflectGetOwnPropertyDescriptor, kNone) \
V(ReflectPreventExtensions, kNone) \ V(ReflectGetPrototypeOf, kNone) \
V(ReflectSet, kNone) \ V(ReflectHas, kNone) \
V(ReflectSetPrototypeOf, kNone) \ V(ReflectIsExtensible, kNone) \
\ V(ReflectOwnKeys, kNone) \
V(SymbolConstructor, kNone) \ V(ReflectPreventExtensions, kNone) \
V(SymbolConstructor_ConstructStub, kTarget) \ V(ReflectSet, kNone) \
\ V(ReflectSetPrototypeOf, kNone) \
V(HandleApiCall, kTarget) \ \
V(HandleApiCallConstruct, kTarget) \ V(SymbolConstructor, kNone) \
V(HandleApiCallAsFunction, kNone) \ V(SymbolConstructor_ConstructStub, kTarget) \
V(HandleApiCallAsConstructor, kNone) \ \
\ V(HandleApiCall, kTarget) \
V(RestrictedFunctionPropertiesThrower, kNone) \ V(HandleApiCallConstruct, kTarget) \
V(HandleApiCallAsFunction, kNone) \
V(HandleApiCallAsConstructor, kNone) \
\
V(RestrictedFunctionPropertiesThrower, kNone) \
V(RestrictedStrictArgumentsPropertiesThrower, kNone) V(RestrictedStrictArgumentsPropertiesThrower, kNone)
// Define list of builtins implemented in assembly. // Define list of builtins implemented in assembly.
......
...@@ -276,6 +276,7 @@ namespace internal { ...@@ -276,6 +276,7 @@ namespace internal {
V(int8x16_string, "int8x16") \ V(int8x16_string, "int8x16") \
V(Int8x16_string, "Int8x16") \ V(Int8x16_string, "Int8x16") \
V(isExtensible_string, "isExtensible") \ V(isExtensible_string, "isExtensible") \
V(isView_string, "isView") \
V(KeyedLoadMonomorphic_string, "KeyedLoadMonomorphic") \ V(KeyedLoadMonomorphic_string, "KeyedLoadMonomorphic") \
V(KeyedStoreMonomorphic_string, "KeyedStoreMonomorphic") \ V(KeyedStoreMonomorphic_string, "KeyedStoreMonomorphic") \
V(last_index_string, "lastIndex") \ V(last_index_string, "lastIndex") \
......
...@@ -12,31 +12,18 @@ ...@@ -12,31 +12,18 @@
// Imports // Imports
var GlobalArrayBuffer = global.ArrayBuffer; var GlobalArrayBuffer = global.ArrayBuffer;
var GlobalObject = global.Object;
var MakeTypeError; var MakeTypeError;
var MaxSimple; var MaxSimple;
var MinSimple; var MinSimple;
var ToPositiveInteger;
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
utils.Import(function(from) { utils.Import(function(from) {
MakeTypeError = from.MakeTypeError; MakeTypeError = from.MakeTypeError;
MaxSimple = from.MaxSimple; MaxSimple = from.MaxSimple;
MinSimple = from.MinSimple; MinSimple = from.MinSimple;
ToPositiveInteger = from.ToPositiveInteger;
}); });
// ------------------------------------------------------------------- // -------------------------------------------------------------------
function ArrayBufferConstructor(length) { // length = 1
if (!IS_UNDEFINED(new.target)) {
var byteLength = ToPositiveInteger(length, kInvalidArrayBufferLength);
%ArrayBufferInitialize(this, byteLength, kNotShared);
} else {
throw MakeTypeError(kConstructorNotFunction, "ArrayBuffer");
}
}
function ArrayBufferGetByteLen() { function ArrayBufferGetByteLen() {
if (!IS_ARRAYBUFFER(this)) { if (!IS_ARRAYBUFFER(this)) {
throw MakeTypeError(kIncompatibleMethodReceiver, throw MakeTypeError(kIncompatibleMethodReceiver,
...@@ -82,29 +69,9 @@ function ArrayBufferSlice(start, end) { ...@@ -82,29 +69,9 @@ function ArrayBufferSlice(start, end) {
return result; return result;
} }
function ArrayBufferIsViewJS(obj) {
return %ArrayBufferIsView(obj);
}
// Set up the ArrayBuffer constructor function.
%SetCode(GlobalArrayBuffer, ArrayBufferConstructor);
%FunctionSetPrototype(GlobalArrayBuffer, new GlobalObject());
// Set up the constructor property on the ArrayBuffer prototype object.
%AddNamedProperty(
GlobalArrayBuffer.prototype, "constructor", GlobalArrayBuffer, DONT_ENUM);
%AddNamedProperty(GlobalArrayBuffer.prototype,
toStringTagSymbol, "ArrayBuffer", DONT_ENUM | READ_ONLY);
utils.InstallGetter(GlobalArrayBuffer.prototype, "byteLength", utils.InstallGetter(GlobalArrayBuffer.prototype, "byteLength",
ArrayBufferGetByteLen); ArrayBufferGetByteLen);
utils.InstallFunctions(GlobalArrayBuffer, DONT_ENUM, [
"isView", ArrayBufferIsViewJS
]);
utils.InstallFunctions(GlobalArrayBuffer.prototype, DONT_ENUM, [ utils.InstallFunctions(GlobalArrayBuffer.prototype, DONT_ENUM, [
"slice", ArrayBufferSlice "slice", ArrayBufferSlice
]); ]);
......
...@@ -9,27 +9,14 @@ ...@@ -9,27 +9,14 @@
%CheckIsBootstrapping(); %CheckIsBootstrapping();
var GlobalSharedArrayBuffer = global.SharedArrayBuffer; var GlobalSharedArrayBuffer = global.SharedArrayBuffer;
var GlobalObject = global.Object;
var MakeTypeError; var MakeTypeError;
var ToPositiveInteger;
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
utils.Import(function(from) { utils.Import(function(from) {
MakeTypeError = from.MakeTypeError; MakeTypeError = from.MakeTypeError;
ToPositiveInteger = from.ToPositiveInteger;
}) })
// ------------------------------------------------------------------- // -------------------------------------------------------------------
function SharedArrayBufferConstructor(length) { // length = 1
if (!IS_UNDEFINED(new.target)) {
var byteLength = ToPositiveInteger(length, kInvalidArrayBufferLength);
%ArrayBufferInitialize(this, byteLength, kShared);
} else {
throw MakeTypeError(kConstructorNotFunction, "SharedArrayBuffer");
}
}
function SharedArrayBufferGetByteLen() { function SharedArrayBufferGetByteLen() {
if (!IS_SHAREDARRAYBUFFER(this)) { if (!IS_SHAREDARRAYBUFFER(this)) {
throw MakeTypeError(kIncompatibleMethodReceiver, throw MakeTypeError(kIncompatibleMethodReceiver,
...@@ -38,27 +25,7 @@ function SharedArrayBufferGetByteLen() { ...@@ -38,27 +25,7 @@ function SharedArrayBufferGetByteLen() {
return %_ArrayBufferGetByteLength(this); return %_ArrayBufferGetByteLength(this);
} }
function SharedArrayBufferIsViewJS(obj) {
return %ArrayBufferIsView(obj);
}
// Set up the SharedArrayBuffer constructor function.
%SetCode(GlobalSharedArrayBuffer, SharedArrayBufferConstructor);
%FunctionSetPrototype(GlobalSharedArrayBuffer, new GlobalObject());
// Set up the constructor property on the SharedArrayBuffer prototype object.
%AddNamedProperty(GlobalSharedArrayBuffer.prototype, "constructor",
GlobalSharedArrayBuffer, DONT_ENUM);
%AddNamedProperty(GlobalSharedArrayBuffer.prototype,
toStringTagSymbol, "SharedArrayBuffer", DONT_ENUM | READ_ONLY);
utils.InstallGetter(GlobalSharedArrayBuffer.prototype, "byteLength", utils.InstallGetter(GlobalSharedArrayBuffer.prototype, "byteLength",
SharedArrayBufferGetByteLen); SharedArrayBufferGetByteLen);
utils.InstallFunctions(GlobalSharedArrayBuffer, DONT_ENUM, [
"isView", SharedArrayBufferIsViewJS
]);
}) })
...@@ -13,32 +13,6 @@ ...@@ -13,32 +13,6 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
RUNTIME_FUNCTION(Runtime_ArrayBufferInitialize) {
HandleScope scope(isolate);
DCHECK(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, holder, 0);
CONVERT_NUMBER_ARG_HANDLE_CHECKED(byteLength, 1);
CONVERT_BOOLEAN_ARG_CHECKED(is_shared, 2);
if (!holder->byte_length()->IsUndefined()) {
// ArrayBuffer is already initialized; probably a fuzz test.
return *holder;
}
size_t allocated_length = 0;
if (!TryNumberToSize(isolate, *byteLength, &allocated_length)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
}
if (!JSArrayBuffer::SetupAllocatingData(
holder, isolate, allocated_length, true,
is_shared ? SharedFlag::kShared : SharedFlag::kNotShared)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewRangeError(MessageTemplate::kArrayBufferAllocationFailed));
}
return *holder;
}
RUNTIME_FUNCTION(Runtime_ArrayBufferGetByteLength) { RUNTIME_FUNCTION(Runtime_ArrayBufferGetByteLength) {
SealHandleScope shs(isolate); SealHandleScope shs(isolate);
DCHECK(args.length() == 1); DCHECK(args.length() == 1);
...@@ -70,14 +44,6 @@ RUNTIME_FUNCTION(Runtime_ArrayBufferSliceImpl) { ...@@ -70,14 +44,6 @@ RUNTIME_FUNCTION(Runtime_ArrayBufferSliceImpl) {
} }
RUNTIME_FUNCTION(Runtime_ArrayBufferIsView) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_CHECKED(Object, object, 0);
return isolate->heap()->ToBoolean(object->IsJSArrayBufferView());
}
RUNTIME_FUNCTION(Runtime_ArrayBufferNeuter) { RUNTIME_FUNCTION(Runtime_ArrayBufferNeuter) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK(args.length() == 1); DCHECK(args.length() == 1);
......
...@@ -978,10 +978,8 @@ namespace internal { ...@@ -978,10 +978,8 @@ namespace internal {
#define FOR_EACH_INTRINSIC_TYPEDARRAY(F) \ #define FOR_EACH_INTRINSIC_TYPEDARRAY(F) \
F(ArrayBufferInitialize, 3, 1) \
F(ArrayBufferGetByteLength, 1, 1) \ F(ArrayBufferGetByteLength, 1, 1) \
F(ArrayBufferSliceImpl, 3, 1) \ F(ArrayBufferSliceImpl, 3, 1) \
F(ArrayBufferIsView, 1, 1) \
F(ArrayBufferNeuter, 1, 1) \ F(ArrayBufferNeuter, 1, 1) \
F(TypedArrayInitialize, 6, 1) \ F(TypedArrayInitialize, 6, 1) \
F(TypedArrayInitializeFromArrayLike, 4, 1) \ F(TypedArrayInitializeFromArrayLike, 4, 1) \
......
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
try {
} catch(e) {; }
new ArrayBuffer();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment