[builtins] Migrate a bunch of Object builtins to C++.

The Object.freeze, Object.isExtensible, Object.isFrozen,
Object.isSealed, Object.preventExtensions and Object.seal builtins were
already implemented in C++, but they still had some funny JavaScript
wrappers that just called into the C++ implementation on every
(interesting) execution path.

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

Cr-Commit-Position: refs/heads/master@{#33074}
This commit is contained in:
bmeurer 2016-01-04 00:10:13 -08:00 committed by Commit bot
parent 84a88a1bd0
commit 70c4bf1331
13 changed files with 144 additions and 155 deletions

View File

@ -1044,6 +1044,16 @@ static Handle<JSFunction> SimpleInstallFunction(Handle<JSObject> base,
}
static Handle<JSFunction> SimpleInstallFunction(Handle<JSObject> base,
const char* name,
Builtins::Name call, int len,
bool adapt) {
Factory* const factory = base->GetIsolate()->factory();
return SimpleInstallFunction(base, factory->InternalizeUtf8String(name), call,
len, adapt);
}
static void InstallWithIntrinsicDefaultProto(Isolate* isolate,
Handle<JSFunction> function,
int context_index) {
@ -1078,13 +1088,33 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
native_context()->set_script_context_table(*script_context_table);
InstallGlobalThisBinding();
Handle<String> object_name = factory->Object_string();
JSObject::AddProperty(
global_object, object_name, isolate->object_function(), DONT_ENUM);
SimpleInstallFunction(isolate->object_function(), factory->assign_string(),
Builtins::kObjectAssign, 2, false);
SimpleInstallFunction(isolate->object_function(), factory->create_string(),
Builtins::kObjectCreate, 2, false);
{ // --- O b j e c t ---
Handle<String> object_name = factory->Object_string();
Handle<JSFunction> object_function = isolate->object_function();
JSObject::AddProperty(global_object, object_name, object_function,
DONT_ENUM);
SimpleInstallFunction(object_function, factory->assign_string(),
Builtins::kObjectAssign, 2, false);
SimpleInstallFunction(object_function, factory->create_string(),
Builtins::kObjectCreate, 2, false);
Handle<JSFunction> object_freeze = SimpleInstallFunction(
object_function, "freeze", Builtins::kObjectFreeze, 1, false);
native_context()->set_object_freeze(*object_freeze);
Handle<JSFunction> object_is_extensible =
SimpleInstallFunction(object_function, "isExtensible",
Builtins::kObjectIsExtensible, 1, false);
native_context()->set_object_is_extensible(*object_is_extensible);
Handle<JSFunction> object_is_frozen = SimpleInstallFunction(
object_function, "isFrozen", Builtins::kObjectIsFrozen, 1, false);
native_context()->set_object_is_frozen(*object_is_frozen);
Handle<JSFunction> object_is_sealed = SimpleInstallFunction(
object_function, "isSealed", Builtins::kObjectIsSealed, 1, false);
native_context()->set_object_is_sealed(*object_is_sealed);
SimpleInstallFunction(object_function, "preventExtensions",
Builtins::kObjectPreventExtensions, 1, false);
SimpleInstallFunction(object_function, "seal", Builtins::kObjectSeal, 1,
false);
}
Handle<JSObject> global(native_context()->global_object());

View File

@ -1522,6 +1522,84 @@ BUILTIN(ObjectCreate) {
}
// ES6 section 19.1.2.5 Object.freeze ( O )
BUILTIN(ObjectFreeze) {
HandleScope scope(isolate);
Handle<Object> object = args.atOrUndefined(isolate, 1);
if (object->IsJSReceiver()) {
MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
FROZEN, Object::THROW_ON_ERROR),
isolate->heap()->exception());
}
return *object;
}
// ES6 section 19.1.2.11 Object.isExtensible ( O )
BUILTIN(ObjectIsExtensible) {
HandleScope scope(isolate);
Handle<Object> object = args.atOrUndefined(isolate, 1);
Maybe<bool> result =
object->IsJSReceiver()
? JSReceiver::IsExtensible(Handle<JSReceiver>::cast(object))
: Just(false);
MAYBE_RETURN(result, isolate->heap()->exception());
return isolate->heap()->ToBoolean(result.FromJust());
}
// ES6 section 19.1.2.12 Object.isFrozen ( O )
BUILTIN(ObjectIsFrozen) {
HandleScope scope(isolate);
Handle<Object> object = args.atOrUndefined(isolate, 1);
Maybe<bool> result = object->IsJSReceiver()
? JSReceiver::TestIntegrityLevel(
Handle<JSReceiver>::cast(object), FROZEN)
: Just(true);
MAYBE_RETURN(result, isolate->heap()->exception());
return isolate->heap()->ToBoolean(result.FromJust());
}
// ES6 section 19.1.2.13 Object.isSealed ( O )
BUILTIN(ObjectIsSealed) {
HandleScope scope(isolate);
Handle<Object> object = args.atOrUndefined(isolate, 1);
Maybe<bool> result = object->IsJSReceiver()
? JSReceiver::TestIntegrityLevel(
Handle<JSReceiver>::cast(object), SEALED)
: Just(true);
MAYBE_RETURN(result, isolate->heap()->exception());
return isolate->heap()->ToBoolean(result.FromJust());
}
// ES6 section 19.1.2.15 Object.preventExtensions ( O )
BUILTIN(ObjectPreventExtensions) {
HandleScope scope(isolate);
Handle<Object> object = args.atOrUndefined(isolate, 1);
if (object->IsJSReceiver()) {
MAYBE_RETURN(JSReceiver::PreventExtensions(Handle<JSReceiver>::cast(object),
Object::THROW_ON_ERROR),
isolate->heap()->exception());
}
return *object;
}
// ES6 section 19.1.2.17 Object.seal ( O )
BUILTIN(ObjectSeal) {
HandleScope scope(isolate);
Handle<Object> object = args.atOrUndefined(isolate, 1);
if (object->IsJSReceiver()) {
MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
SEALED, Object::THROW_ON_ERROR),
isolate->heap()->exception());
}
return *object;
}
namespace {
bool CodeGenerationFromStringsAllowed(Isolate* isolate,

View File

@ -81,6 +81,12 @@ inline bool operator&(BuiltinExtraArguments lhs, BuiltinExtraArguments rhs) {
\
V(ObjectAssign, kNone) \
V(ObjectCreate, kNone) \
V(ObjectFreeze, kNone) \
V(ObjectIsExtensible, kNone) \
V(ObjectIsFrozen, kNone) \
V(ObjectIsSealed, kNone) \
V(ObjectPreventExtensions, kNone) \
V(ObjectSeal, kNone) \
V(ObjectProtoToString, kNone) \
\
V(ProxyConstructor, kNone) \

View File

@ -83,6 +83,10 @@ enum BindingFlags {
V(GET_TEMPLATE_CALL_SITE_INDEX, JSFunction, get_template_call_site) \
V(MAKE_RANGE_ERROR_INDEX, JSFunction, make_range_error) \
V(MAKE_TYPE_ERROR_INDEX, JSFunction, make_type_error) \
V(OBJECT_FREEZE, JSFunction, object_freeze) \
V(OBJECT_IS_EXTENSIBLE, JSFunction, object_is_extensible) \
V(OBJECT_IS_FROZEN, JSFunction, object_is_frozen) \
V(OBJECT_IS_SEALED, JSFunction, object_is_sealed) \
V(REFLECT_APPLY_INDEX, JSFunction, reflect_apply) \
V(REFLECT_CONSTRUCT_INDEX, JSFunction, reflect_construct) \
V(REFLECT_DEFINE_PROPERTY_INDEX, JSFunction, reflect_define_property) \

View File

@ -23,8 +23,6 @@ var MaxSimple;
var MinSimple;
var ObjectDefineProperty;
var ObjectHasOwnProperty;
var ObjectIsFrozen;
var ObjectIsSealed;
var ObjectToString = utils.ImportNow("object_to_string");
var ObserveBeginPerformSplice;
var ObserveEndPerformSplice;
@ -42,8 +40,6 @@ utils.Import(function(from) {
MinSimple = from.MinSimple;
ObjectDefineProperty = from.ObjectDefineProperty;
ObjectHasOwnProperty = from.ObjectHasOwnProperty;
ObjectIsFrozen = from.ObjectIsFrozen;
ObjectIsSealed = from.ObjectIsSealed;
ObserveBeginPerformSplice = from.ObserveBeginPerformSplice;
ObserveEndPerformSplice = from.ObserveEndPerformSplice;
ObserveEnqueueSpliceRecord = from.ObserveEnqueueSpliceRecord;
@ -672,7 +668,7 @@ function ArrayShift() {
return;
}
if (ObjectIsSealed(array)) throw MakeTypeError(kArrayFunctionsOnSealed);
if (%object_is_sealed(array)) throw MakeTypeError(kArrayFunctionsOnSealed);
if (%IsObserved(array))
return ObservedArrayShift.call(array, len);
@ -723,7 +719,7 @@ function ArrayUnshift(arg1) { // length == 1
var num_arguments = %_ArgumentsLength();
if (len > 0 && UseSparseVariant(array, len, IS_ARRAY(array), len) &&
!ObjectIsSealed(array)) {
!%object_is_sealed(array)) {
SparseMove(array, 0, 0, len, num_arguments);
} else {
SimpleMove(array, 0, 0, len, num_arguments);
@ -869,9 +865,9 @@ function ArraySplice(start, delete_count) {
deleted_elements.length = del_count;
var num_elements_to_add = num_arguments > 2 ? num_arguments - 2 : 0;
if (del_count != num_elements_to_add && ObjectIsSealed(array)) {
if (del_count != num_elements_to_add && %object_is_sealed(array)) {
throw MakeTypeError(kArrayFunctionsOnSealed);
} else if (del_count > 0 && ObjectIsFrozen(array)) {
} else if (del_count > 0 && %object_is_frozen(array)) {
throw MakeTypeError(kArrayFunctionsOnFrozen);
}
@ -1675,7 +1671,7 @@ function InnerArrayFill(value, start, end, array, length) {
if (end > length) end = length;
}
if ((end - i) > 0 && ObjectIsFrozen(array)) {
if ((end - i) > 0 && %object_is_frozen(array)) {
throw MakeTypeError(kArrayFunctionsOnFrozen);
}

View File

@ -16,14 +16,10 @@ var GlobalArray = global.Array;
var GlobalObject = global.Object;
var InternalArray = utils.InternalArray;
var MakeTypeError;
var ObjectFreeze;
var ObjectIsFrozen;
utils.Import(function(from) {
GetHash = from.GetHash;
MakeTypeError = from.MakeTypeError;
ObjectFreeze = from.ObjectFreeze;
ObjectIsFrozen = from.ObjectIsFrozen;
});
// -------------------------------------------------------------------
@ -388,7 +384,7 @@ function ObjectObserve(object, callback, acceptList) {
throw MakeTypeError(kObserveAccessChecked, "observe");
if (!IS_CALLABLE(callback))
throw MakeTypeError(kObserveNonFunction, "observe");
if (ObjectIsFrozen(callback))
if (%object_is_frozen(callback))
throw MakeTypeError(kObserveCallbackFrozen);
var objectObserveFn = %GetObjectContextObjectObserve(object);
@ -481,7 +477,7 @@ function ObjectInfoEnqueueExternalChangeRecord(objectInfo, changeRecord, type) {
%DefineDataPropertyUnchecked(
newRecord, prop, changeRecord[prop], READ_ONLY + DONT_DELETE);
}
ObjectFreeze(newRecord);
%object_freeze(newRecord);
ObjectInfoEnqueueInternalChangeRecord(objectInfo, newRecord);
}
@ -533,8 +529,8 @@ function EnqueueSpliceRecord(array, index, removed, addedCount) {
addedCount: addedCount
};
ObjectFreeze(changeRecord);
ObjectFreeze(changeRecord.removed);
%object_freeze(changeRecord);
%object_freeze(changeRecord.removed);
ObjectInfoEnqueueInternalChangeRecord(objectInfo, changeRecord);
}
@ -558,7 +554,7 @@ function NotifyChange(type, object, name, oldValue) {
};
}
ObjectFreeze(changeRecord);
%object_freeze(changeRecord);
ObjectInfoEnqueueInternalChangeRecord(objectInfo, changeRecord);
}
@ -617,7 +613,7 @@ function ObjectGetNotifier(object) {
if (%IsAccessCheckNeeded(object))
throw MakeTypeError(kObserveAccessChecked, "getNotifier");
if (ObjectIsFrozen(object)) return null;
if (%object_is_frozen(object)) return null;
if (!%ObjectWasCreatedInCurrentOrigin(object)) return null;

View File

@ -196,7 +196,6 @@ function PostNatives(utils) {
"MathMin",
"MaxSimple",
"MinSimple",
"ObjectIsFrozen",
"ObjectDefineProperty",
"ObserveArrayMethods",
"ObserveObjectMethods",
@ -214,6 +213,9 @@ function PostNatives(utils) {
"iterator_symbol",
"promise_status_symbol",
"promise_value_symbol",
"object_freeze",
"object_is_frozen",
"object_is_sealed",
"reflect_apply",
"reflect_construct",
"regexp_flags_symbol",

View File

@ -70,10 +70,10 @@ function GetTemplateCallSite(siteObj, rawStrings, hash) {
if (!IS_UNDEFINED(cached)) return cached;
%AddNamedProperty(siteObj, "raw", %ObjectFreeze(rawStrings),
%AddNamedProperty(siteObj, "raw", %object_freeze(rawStrings),
READ_ONLY | DONT_ENUM | DONT_DELETE);
return SetCachedCallSite(%ObjectFreeze(siteObj), hash);
return SetCachedCallSite(%object_freeze(siteObj), hash);
}
// ----------------------------------------------------------------------------

View File

@ -539,7 +539,7 @@ function DefineProxyProperty(obj, p, attributes, should_throw) {
function DefineObjectProperty(obj, p, desc, should_throw) {
var current_array = %GetOwnProperty_Legacy(obj, TO_NAME(p));
var current = ConvertDescriptorArrayToDescriptor(current_array);
var extensible = %IsExtensible(obj);
var extensible = %object_is_extensible(obj);
if (IS_UNDEFINED(current) && !extensible) {
if (should_throw) {
@ -838,48 +838,6 @@ function ObjectDefineProperties(obj, properties) {
}
// ES6 19.1.2.17
function ObjectSealJS(obj) {
if (!IS_RECEIVER(obj)) return obj;
return %ObjectSeal(obj);
}
// ES6 19.1.2.5
function ObjectFreezeJS(obj) {
if (!IS_RECEIVER(obj)) return obj;
return %ObjectFreeze(obj);
}
// ES6 19.1.2.15
function ObjectPreventExtension(obj) {
if (!IS_RECEIVER(obj)) return obj;
return %PreventExtensions(obj);
}
// ES6 19.1.2.13
function ObjectIsSealed(obj) {
if (!IS_RECEIVER(obj)) return true;
return %ObjectIsSealed(obj);
}
// ES6 19.1.2.12
function ObjectIsFrozen(obj) {
if (!IS_RECEIVER(obj)) return true;
return %ObjectIsFrozen(obj);
}
// ES6 19.1.2.11
function ObjectIsExtensible(obj) {
if (!IS_RECEIVER(obj)) return false;
return %IsExtensible(obj);
}
// ES6 B.2.2.1.1
function ObjectGetProto() {
return %_GetPrototype(TO_OBJECT(this));
@ -937,18 +895,12 @@ utils.InstallFunctions(GlobalObject, DONT_ENUM, [
"keys", ObjectKeys,
"defineProperty", ObjectDefineProperty,
"defineProperties", ObjectDefineProperties,
"freeze", ObjectFreezeJS,
"getPrototypeOf", ObjectGetPrototypeOf,
"setPrototypeOf", ObjectSetPrototypeOf,
"getOwnPropertyDescriptor", ObjectGetOwnPropertyDescriptor,
"getOwnPropertyNames", ObjectGetOwnPropertyNames,
// getOwnPropertySymbols is added in symbol.js.
"is", SameValue, // ECMA-262, Edition 6, section 19.1.2.10
"isExtensible", ObjectIsExtensible,
"isFrozen", ObjectIsFrozen,
"isSealed", ObjectIsSealed,
"preventExtensions", ObjectPreventExtension,
"seal", ObjectSealJS
// deliverChangeRecords, getNotifier, observe and unobserve are added
// in object-observe.js.
]);
@ -1257,10 +1209,7 @@ utils.Export(function(to) {
to.NumberIsNaN = NumberIsNaN;
to.ObjectDefineProperties = ObjectDefineProperties;
to.ObjectDefineProperty = ObjectDefineProperty;
to.ObjectFreeze = ObjectFreezeJS;
to.ObjectHasOwnProperty = ObjectHasOwnProperty;
to.ObjectIsFrozen = ObjectIsFrozen;
to.ObjectIsSealed = ObjectIsSealed;
to.ObjectKeys = ObjectKeys;
});

View File

@ -291,26 +291,6 @@ RUNTIME_FUNCTION(Runtime_GetOwnProperty) {
}
RUNTIME_FUNCTION(Runtime_PreventExtensions) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
MAYBE_RETURN(JSReceiver::PreventExtensions(obj, Object::THROW_ON_ERROR),
isolate->heap()->exception());
return *obj;
}
RUNTIME_FUNCTION(Runtime_IsExtensible) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
Maybe<bool> result = JSReceiver::IsExtensible(obj);
MAYBE_RETURN(result, isolate->heap()->exception());
return isolate->heap()->ToBoolean(result.FromJust());
}
RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
@ -326,52 +306,6 @@ RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) {
}
RUNTIME_FUNCTION(Runtime_ObjectFreeze) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
MAYBE_RETURN(
JSReceiver::SetIntegrityLevel(object, FROZEN, Object::THROW_ON_ERROR),
isolate->heap()->exception());
return *object;
}
RUNTIME_FUNCTION(Runtime_ObjectIsFrozen) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
Maybe<bool> result = JSReceiver::TestIntegrityLevel(object, FROZEN);
MAYBE_RETURN(result, isolate->heap()->exception());
return isolate->heap()->ToBoolean(result.FromJust());
}
RUNTIME_FUNCTION(Runtime_ObjectSeal) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
MAYBE_RETURN(
JSReceiver::SetIntegrityLevel(object, SEALED, Object::THROW_ON_ERROR),
isolate->heap()->exception());
return *object;
}
RUNTIME_FUNCTION(Runtime_ObjectIsSealed) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
Maybe<bool> result = JSReceiver::TestIntegrityLevel(object, SEALED);
MAYBE_RETURN(result, isolate->heap()->exception());
return isolate->heap()->ToBoolean(result.FromJust());
}
RUNTIME_FUNCTION(Runtime_LoadGlobalViaContext) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());

View File

@ -423,13 +423,7 @@ namespace internal {
F(SetPrototype, 2, 1) \
F(GetOwnProperty, 2, 1) \
F(GetOwnProperty_Legacy, 2, 1) \
F(PreventExtensions, 1, 1) \
F(IsExtensible, 1, 1) \
F(OptimizeObjectForAddingMultipleProperties, 2, 1) \
F(ObjectFreeze, 1, 1) \
F(ObjectIsFrozen, 1, 1) \
F(ObjectSeal, 1, 1) \
F(ObjectIsSealed, 1, 1) \
F(GetProperty, 2, 1) \
F(GetPropertyStrong, 2, 1) \
F(KeyedGetProperty, 2, 1) \

View File

@ -6,7 +6,7 @@
function f() {
var e = [0];
%PreventExtensions(e);
Object.preventExtensions(e);
for (var i = 0; i < 4; i++) e.shift();
}

View File

@ -6,7 +6,7 @@
function __f_6() {
var __v_7 = [0];
%PreventExtensions(__v_7);
Object.preventExtensions(__v_7);
for (var __v_6 = -2; __v_6 < 19; __v_6++) __v_7.shift();
__f_7(__v_7);
}