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 {
DECLARE_FEATURE_INITIALIZATION(promise_extra, "")
#undef DECLARE_FEATURE_INITIALIZATION
Handle<JSFunction> InstallArrayBuffer(Handle<JSObject> target,
const char* name);
Handle<JSFunction> InstallInternalArray(Handle<JSObject> target,
const char* name,
ElementsKind elements_kind);
......@@ -1345,11 +1347,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
{ // -- A r r a y B u f f e r
Handle<JSFunction> array_buffer_fun =
InstallFunction(
global, "ArrayBuffer", JS_ARRAY_BUFFER_TYPE,
JSArrayBuffer::kSizeWithInternalFields,
isolate->initial_object_prototype(),
Builtins::kIllegal);
InstallArrayBuffer(global, "ArrayBuffer");
InstallWithIntrinsicDefaultProto(isolate, array_buffer_fun,
Context::ARRAY_BUFFER_FUN_INDEX);
}
......@@ -2237,13 +2235,9 @@ void Genesis::InitializeGlobal_harmony_reflect() {
void Genesis::InitializeGlobal_harmony_sharedarraybuffer() {
if (!FLAG_harmony_sharedarraybuffer) return;
Handle<JSGlobalObject> global(
JSGlobalObject::cast(native_context()->global_object()));
Handle<JSFunction> shared_array_buffer_fun = InstallFunction(
global, "SharedArrayBuffer", JS_ARRAY_BUFFER_TYPE,
JSArrayBuffer::kSizeWithInternalFields,
isolate()->initial_object_prototype(), Builtins::kIllegal);
Handle<JSGlobalObject> global(native_context()->global_object());
Handle<JSFunction> shared_array_buffer_fun =
InstallArrayBuffer(global, "SharedArrayBuffer");
native_context()->set_shared_array_buffer_fun(*shared_array_buffer_fun);
}
......@@ -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,
const char* name,
ElementsKind elements_kind) {
......
......@@ -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.
BUILTIN(ProxyConstructor) {
HandleScope scope(isolate);
......
......@@ -51,58 +51,62 @@ inline bool operator&(BuiltinExtraArguments lhs, BuiltinExtraArguments rhs) {
// Define list of builtins implemented in C++.
#define BUILTIN_LIST_C(V) \
V(Illegal, kNone) \
\
V(EmptyFunction, kNone) \
\
V(ArrayConcat, kNone) \
V(ArrayIsArray, kNone) \
V(ArrayPop, kNone) \
V(ArrayPush, kNone) \
V(ArrayShift, kNone) \
V(ArraySlice, kNone) \
V(ArraySplice, kNone) \
V(ArrayUnshift, kNone) \
\
V(DateToPrimitive, kNone) \
\
V(FunctionConstructor, kTargetAndNewTarget) \
V(FunctionPrototypeBind, kNone) \
V(FunctionPrototypeToString, kNone) \
\
V(GeneratorFunctionConstructor, kTargetAndNewTarget) \
\
V(GlobalEval, kTarget) \
\
V(ObjectAssign, kNone) \
V(ObjectCreate, kNone) \
V(ObjectProtoToString, kNone) \
\
V(ProxyConstructor, kNone) \
V(ProxyConstructor_ConstructStub, kTarget) \
\
V(ReflectDefineProperty, kNone) \
V(ReflectDeleteProperty, kNone) \
V(ReflectGet, kNone) \
V(ReflectGetOwnPropertyDescriptor, kNone) \
V(ReflectGetPrototypeOf, kNone) \
V(ReflectHas, kNone) \
V(ReflectIsExtensible, kNone) \
V(ReflectOwnKeys, kNone) \
V(ReflectPreventExtensions, kNone) \
V(ReflectSet, kNone) \
V(ReflectSetPrototypeOf, kNone) \
\
V(SymbolConstructor, kNone) \
V(SymbolConstructor_ConstructStub, kTarget) \
\
V(HandleApiCall, kTarget) \
V(HandleApiCallConstruct, kTarget) \
V(HandleApiCallAsFunction, kNone) \
V(HandleApiCallAsConstructor, kNone) \
\
V(RestrictedFunctionPropertiesThrower, kNone) \
#define BUILTIN_LIST_C(V) \
V(Illegal, kNone) \
\
V(EmptyFunction, kNone) \
\
V(ArrayConcat, kNone) \
V(ArrayIsArray, kNone) \
V(ArrayPop, kNone) \
V(ArrayPush, kNone) \
V(ArrayShift, kNone) \
V(ArraySlice, kNone) \
V(ArraySplice, kNone) \
V(ArrayUnshift, kNone) \
\
V(ArrayBufferConstructor, kTarget) \
V(ArrayBufferConstructor_ConstructStub, kTargetAndNewTarget) \
V(ArrayBufferIsView, kNone) \
\
V(DateToPrimitive, kNone) \
\
V(FunctionConstructor, kTargetAndNewTarget) \
V(FunctionPrototypeBind, kNone) \
V(FunctionPrototypeToString, kNone) \
\
V(GeneratorFunctionConstructor, kTargetAndNewTarget) \
\
V(GlobalEval, kTarget) \
\
V(ObjectAssign, kNone) \
V(ObjectCreate, kNone) \
V(ObjectProtoToString, kNone) \
\
V(ProxyConstructor, kNone) \
V(ProxyConstructor_ConstructStub, kTarget) \
\
V(ReflectDefineProperty, kNone) \
V(ReflectDeleteProperty, kNone) \
V(ReflectGet, kNone) \
V(ReflectGetOwnPropertyDescriptor, kNone) \
V(ReflectGetPrototypeOf, kNone) \
V(ReflectHas, kNone) \
V(ReflectIsExtensible, kNone) \
V(ReflectOwnKeys, kNone) \
V(ReflectPreventExtensions, kNone) \
V(ReflectSet, kNone) \
V(ReflectSetPrototypeOf, kNone) \
\
V(SymbolConstructor, kNone) \
V(SymbolConstructor_ConstructStub, kTarget) \
\
V(HandleApiCall, kTarget) \
V(HandleApiCallConstruct, kTarget) \
V(HandleApiCallAsFunction, kNone) \
V(HandleApiCallAsConstructor, kNone) \
\
V(RestrictedFunctionPropertiesThrower, kNone) \
V(RestrictedStrictArgumentsPropertiesThrower, kNone)
// Define list of builtins implemented in assembly.
......
......@@ -276,6 +276,7 @@ namespace internal {
V(int8x16_string, "int8x16") \
V(Int8x16_string, "Int8x16") \
V(isExtensible_string, "isExtensible") \
V(isView_string, "isView") \
V(KeyedLoadMonomorphic_string, "KeyedLoadMonomorphic") \
V(KeyedStoreMonomorphic_string, "KeyedStoreMonomorphic") \
V(last_index_string, "lastIndex") \
......
......@@ -12,31 +12,18 @@
// Imports
var GlobalArrayBuffer = global.ArrayBuffer;
var GlobalObject = global.Object;
var MakeTypeError;
var MaxSimple;
var MinSimple;
var ToPositiveInteger;
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
utils.Import(function(from) {
MakeTypeError = from.MakeTypeError;
MaxSimple = from.MaxSimple;
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() {
if (!IS_ARRAYBUFFER(this)) {
throw MakeTypeError(kIncompatibleMethodReceiver,
......@@ -82,29 +69,9 @@ function ArrayBufferSlice(start, end) {
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",
ArrayBufferGetByteLen);
utils.InstallFunctions(GlobalArrayBuffer, DONT_ENUM, [
"isView", ArrayBufferIsViewJS
]);
utils.InstallFunctions(GlobalArrayBuffer.prototype, DONT_ENUM, [
"slice", ArrayBufferSlice
]);
......
......@@ -9,27 +9,14 @@
%CheckIsBootstrapping();
var GlobalSharedArrayBuffer = global.SharedArrayBuffer;
var GlobalObject = global.Object;
var MakeTypeError;
var ToPositiveInteger;
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
utils.Import(function(from) {
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() {
if (!IS_SHAREDARRAYBUFFER(this)) {
throw MakeTypeError(kIncompatibleMethodReceiver,
......@@ -38,27 +25,7 @@ function SharedArrayBufferGetByteLen() {
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",
SharedArrayBufferGetByteLen);
utils.InstallFunctions(GlobalSharedArrayBuffer, DONT_ENUM, [
"isView", SharedArrayBufferIsViewJS
]);
})
......@@ -13,32 +13,6 @@
namespace v8 {
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) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 1);
......@@ -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) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
......
......@@ -978,10 +978,8 @@ namespace internal {
#define FOR_EACH_INTRINSIC_TYPEDARRAY(F) \
F(ArrayBufferInitialize, 3, 1) \
F(ArrayBufferGetByteLength, 1, 1) \
F(ArrayBufferSliceImpl, 3, 1) \
F(ArrayBufferIsView, 1, 1) \
F(ArrayBufferNeuter, 1, 1) \
F(TypedArrayInitialize, 6, 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