Commit fc8c4ef2 authored by Z Nguyen-Huu's avatar Z Nguyen-Huu Committed by Commit Bot

Implement fastpath for proxy trap setPrototypeOf

ObjectSetPrototypeOf and ReflectSetPrototypeOf are now Torque builtins (previously CPP) and the Proxy path is implemented completely in Torque while everything else calls into runtime (and is thus a bit slower than previously).

Perf improvement in micro-benchmark JSTests/Proxies
Before:
SetPrototypeOfWithoutTrap-Proxies(Score): 120
SetPrototypeOfWithTrap-Proxies(Score): 112

After:
SetPrototypeOfWithoutTrap-Proxies(Score): 131
SetPrototypeOfWithTrap-Proxies(Score): 127

Bug: v8:6664
Change-Id: I630096e1964c91d1ec39e19f380a2e9e948de4bb
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1669787
Commit-Queue: Z Nguyen-Huu <duongn@microsoft.com>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62402}
parent 9f8561be
...@@ -964,6 +964,7 @@ torque_files = [ ...@@ -964,6 +964,7 @@ torque_files = [
"src/builtins/proxy-revocable.tq", "src/builtins/proxy-revocable.tq",
"src/builtins/proxy-revoke.tq", "src/builtins/proxy-revoke.tq",
"src/builtins/proxy-set-property.tq", "src/builtins/proxy-set-property.tq",
"src/builtins/proxy-set-prototype-of.tq",
"src/builtins/proxy.tq", "src/builtins/proxy.tq",
"src/builtins/reflect.tq", "src/builtins/reflect.tq",
"src/builtins/regexp-replace.tq", "src/builtins/regexp-replace.tq",
......
...@@ -1006,6 +1006,8 @@ const kCalledNonCallable: constexpr MessageTemplate ...@@ -1006,6 +1006,8 @@ const kCalledNonCallable: constexpr MessageTemplate
generates 'MessageTemplate::kCalledNonCallable'; generates 'MessageTemplate::kCalledNonCallable';
const kCalledOnNullOrUndefined: constexpr MessageTemplate const kCalledOnNullOrUndefined: constexpr MessageTemplate
generates 'MessageTemplate::kCalledOnNullOrUndefined'; generates 'MessageTemplate::kCalledOnNullOrUndefined';
const kProtoObjectOrNull: constexpr MessageTemplate
generates 'MessageTemplate::kProtoObjectOrNull';
const kInvalidOffset: constexpr MessageTemplate const kInvalidOffset: constexpr MessageTemplate
generates 'MessageTemplate::kInvalidOffset'; generates 'MessageTemplate::kInvalidOffset';
const kInvalidTypedArrayLength: constexpr MessageTemplate const kInvalidTypedArrayLength: constexpr MessageTemplate
...@@ -2834,6 +2836,8 @@ macro NumberIsNaN(number: Number): bool { ...@@ -2834,6 +2836,8 @@ macro NumberIsNaN(number: Number): bool {
extern macro GotoIfForceSlowPath() labels Taken; extern macro GotoIfForceSlowPath() labels Taken;
extern macro BranchIfToBooleanIsTrue(Object): never extern macro BranchIfToBooleanIsTrue(Object): never
labels Taken, NotTaken; labels Taken, NotTaken;
extern macro BranchIfToBooleanIsFalse(Object): never
labels Taken, NotTaken;
macro ToBoolean(obj: Object): bool { macro ToBoolean(obj: Object): bool {
if (BranchIfToBooleanIsTrue(obj)) { if (BranchIfToBooleanIsTrue(obj)) {
......
...@@ -726,7 +726,6 @@ namespace internal { ...@@ -726,7 +726,6 @@ namespace internal {
CPP(ObjectGetOwnPropertyDescriptors) \ CPP(ObjectGetOwnPropertyDescriptors) \
TFJ(ObjectGetOwnPropertyNames, 1, kReceiver, kObject) \ TFJ(ObjectGetOwnPropertyNames, 1, kReceiver, kObject) \
CPP(ObjectGetOwnPropertySymbols) \ CPP(ObjectGetOwnPropertySymbols) \
CPP(ObjectSetPrototypeOf) \
TFJ(ObjectIs, 2, kReceiver, kLeft, kRight) \ TFJ(ObjectIs, 2, kReceiver, kLeft, kRight) \
CPP(ObjectIsFrozen) \ CPP(ObjectIsFrozen) \
CPP(ObjectIsSealed) \ CPP(ObjectIsSealed) \
...@@ -826,7 +825,6 @@ namespace internal { ...@@ -826,7 +825,6 @@ namespace internal {
TFJ(ReflectHas, 2, kReceiver, kTarget, kKey) \ TFJ(ReflectHas, 2, kReceiver, kTarget, kKey) \
CPP(ReflectOwnKeys) \ CPP(ReflectOwnKeys) \
CPP(ReflectSet) \ CPP(ReflectSet) \
CPP(ReflectSetPrototypeOf) \
\ \
/* RegExp */ \ /* RegExp */ \
CPP(RegExpCapture1Getter) \ CPP(RegExpCapture1Getter) \
......
...@@ -218,39 +218,6 @@ BUILTIN(ObjectFreeze) { ...@@ -218,39 +218,6 @@ BUILTIN(ObjectFreeze) {
return *object; return *object;
} }
// ES6 section 19.1.2.21 Object.setPrototypeOf ( O, proto )
BUILTIN(ObjectSetPrototypeOf) {
HandleScope scope(isolate);
// 1. Let O be ? RequireObjectCoercible(O).
Handle<Object> object = args.atOrUndefined(isolate, 1);
if (object->IsNullOrUndefined(isolate)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
isolate->factory()->NewStringFromAsciiChecked(
"Object.setPrototypeOf")));
}
// 2. If Type(proto) is neither Object nor Null, throw a TypeError exception.
Handle<Object> proto = args.atOrUndefined(isolate, 2);
if (!proto->IsNull(isolate) && !proto->IsJSReceiver()) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, proto));
}
// 3. If Type(O) is not Object, return O.
if (!object->IsJSReceiver()) return *object;
Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
// 4. Let status be ? O.[[SetPrototypeOf]](proto).
// 5. If status is false, throw a TypeError exception.
MAYBE_RETURN(JSReceiver::SetPrototype(receiver, proto, true, kThrowOnError),
ReadOnlyRoots(isolate).exception());
// 6. Return O.
return *receiver;
}
// ES6 section B.2.2.1.1 get Object.prototype.__proto__ // ES6 section B.2.2.1.1 get Object.prototype.__proto__
BUILTIN(ObjectPrototypeGetProto) { BUILTIN(ObjectPrototypeGetProto) {
HandleScope scope(isolate); HandleScope scope(isolate);
......
...@@ -168,30 +168,5 @@ BUILTIN(ReflectSet) { ...@@ -168,30 +168,5 @@ BUILTIN(ReflectSet) {
return *isolate->factory()->ToBoolean(result.FromJust()); return *isolate->factory()->ToBoolean(result.FromJust());
} }
// ES6 section 26.1.14 Reflect.setPrototypeOf
BUILTIN(ReflectSetPrototypeOf) {
HandleScope scope(isolate);
DCHECK_EQ(3, args.length());
Handle<Object> target = args.at(1);
Handle<Object> proto = args.at(2);
if (!target->IsJSReceiver()) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
isolate->factory()->NewStringFromAsciiChecked(
"Reflect.setPrototypeOf")));
}
if (!proto->IsJSReceiver() && !proto->IsNull(isolate)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, proto));
}
Maybe<bool> result = JSReceiver::SetPrototype(
Handle<JSReceiver>::cast(target), proto, true, kDontThrow);
MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
return *isolate->factory()->ToBoolean(result.FromJust());
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -16,6 +16,14 @@ namespace runtime { ...@@ -16,6 +16,14 @@ namespace runtime {
extern transitioning runtime extern transitioning runtime
JSReceiverGetPrototypeOf(implicit context: Context)(JSReceiver): Object; JSReceiverGetPrototypeOf(implicit context: Context)(JSReceiver): Object;
extern transitioning runtime
JSReceiverSetPrototypeOfThrow(implicit context: Context)(JSReceiver, Object):
Object;
extern transitioning runtime
JSReceiverSetPrototypeOfDontThrow(implicit context:
Context)(JSReceiver, Object): Object;
} // namespace runtime } // namespace runtime
namespace object { namespace object {
...@@ -34,7 +42,7 @@ namespace object { ...@@ -34,7 +42,7 @@ namespace object {
const objectJSProxy = Cast<JSProxy>(objectJSReceiver) const objectJSProxy = Cast<JSProxy>(objectJSReceiver)
otherwise return runtime::JSReceiverPreventExtensionsThrow( otherwise return runtime::JSReceiverPreventExtensionsThrow(
objectJSReceiver); objectJSReceiver);
const _status: Object = proxy::ProxyPreventExtensions(objectJSProxy, True); proxy::ProxyPreventExtensions(objectJSProxy, True);
return objectJSReceiver; return objectJSReceiver;
} }
...@@ -61,6 +69,27 @@ namespace object { ...@@ -61,6 +69,27 @@ namespace object {
otherwise return runtime::JSReceiverGetPrototypeOf(object); otherwise return runtime::JSReceiverGetPrototypeOf(object);
return proxy::ProxyGetPrototypeOf(objectJSProxy); return proxy::ProxyGetPrototypeOf(objectJSProxy);
} }
transitioning macro
ObjectSetPrototypeOfThrow(implicit context: Context)(
object: Object, proto: Object): Object {
const objectJSReceiver = Cast<JSReceiver>(object) otherwise return object;
const objectJSProxy = Cast<JSProxy>(objectJSReceiver)
otherwise return runtime::JSReceiverSetPrototypeOfThrow(
objectJSReceiver, proto);
proxy::ProxySetPrototypeOf(objectJSProxy, proto, True);
return objectJSReceiver;
}
transitioning macro
ObjectSetPrototypeOfDontThrow(implicit context: Context)(
object: Object, proto: Object): Object {
const objectJSReceiver = Cast<JSReceiver>(object) otherwise return False;
const objectJSProxy = Cast<JSProxy>(objectJSReceiver)
otherwise return runtime::JSReceiverSetPrototypeOfDontThrow(
objectJSReceiver, proto);
return proxy::ProxySetPrototypeOf(objectJSProxy, proto, False);
}
} // namespace object } // namespace object
namespace object_isextensible { namespace object_isextensible {
...@@ -86,3 +115,25 @@ namespace object_getprototypeof { ...@@ -86,3 +115,25 @@ namespace object_getprototypeof {
return object::ObjectGetPrototypeOf(object); return object::ObjectGetPrototypeOf(object);
} }
} // namespace object_getprototypeof } // namespace object_getprototypeof
namespace object_setprototypeof {
// ES6 section 19.1.2.21 Object.setPrototypeOf ( O, proto )
transitioning javascript builtin ObjectSetPrototypeOf(
js-implicit context:
Context)(_receiver: Object, object: Object, proto: Object): Object {
// 1. Set O to ? RequireObjectCoercible(O).
if (IsNullOrUndefined(object)) {
ThrowTypeError(kCalledOnNullOrUndefined, 'Object.setPrototypeOf');
}
// 2. If Type(proto) is neither Object nor Null, throw a TypeError
// exception.
// 3. If Type(O) is not Object, return O.
// 4. Let status be ? O.[[SetPrototypeOf]](proto).
// 5. If status is false, throw a TypeError exception.
// 6. Return O.
if (proto == Null || Is<JSReceiver>(proto)) {
return object::ObjectSetPrototypeOfThrow(object, proto);
}
ThrowTypeError(kProtoObjectOrNull, proto);
}
} // namespace object_setprototypeof
...@@ -16,6 +16,7 @@ namespace proxy { ...@@ -16,6 +16,7 @@ namespace proxy {
// 1. Let handler be O.[[ProxyHandler]]. // 1. Let handler be O.[[ProxyHandler]].
// 2. If handler is null, throw a TypeError exception. // 2. If handler is null, throw a TypeError exception.
// 3. Assert: Type(handler) is Object. // 3. Assert: Type(handler) is Object.
assert(proxy.handler == Null || Is<JSReceiver>(proxy.handler));
const handler = const handler =
Cast<JSReceiver>(proxy.handler) otherwise ThrowProxyHandlerRevoked; Cast<JSReceiver>(proxy.handler) otherwise ThrowProxyHandlerRevoked;
......
...@@ -22,6 +22,7 @@ namespace proxy { ...@@ -22,6 +22,7 @@ namespace proxy {
// 2. Let handler be O.[[ProxyHandler]]. // 2. Let handler be O.[[ProxyHandler]].
// 3. If handler is null, throw a TypeError exception. // 3. If handler is null, throw a TypeError exception.
// 4. Assert: Type(handler) is Object. // 4. Assert: Type(handler) is Object.
assert(proxy.handler == Null || Is<JSReceiver>(proxy.handler));
const handler = const handler =
Cast<JSReceiver>(proxy.handler) otherwise ThrowProxyHandlerRevoked; Cast<JSReceiver>(proxy.handler) otherwise ThrowProxyHandlerRevoked;
......
...@@ -16,6 +16,7 @@ namespace proxy { ...@@ -16,6 +16,7 @@ namespace proxy {
// 1. Let handler be O.[[ProxyHandler]]. // 1. Let handler be O.[[ProxyHandler]].
// 2. If handler is null, throw a TypeError exception. // 2. If handler is null, throw a TypeError exception.
// 3. Assert: Type(handler) is Object. // 3. Assert: Type(handler) is Object.
assert(proxy.handler == Null || Is<JSReceiver>(proxy.handler));
const handler = const handler =
Cast<JSReceiver>(proxy.handler) otherwise ThrowProxyHandlerRevoked; Cast<JSReceiver>(proxy.handler) otherwise ThrowProxyHandlerRevoked;
......
...@@ -17,6 +17,7 @@ namespace proxy { ...@@ -17,6 +17,7 @@ namespace proxy {
// 1. Let handler be O.[[ProxyHandler]]. // 1. Let handler be O.[[ProxyHandler]].
// 2. If handler is null, throw a TypeError exception. // 2. If handler is null, throw a TypeError exception.
// 3. Assert: Type(handler) is Object. // 3. Assert: Type(handler) is Object.
assert(proxy.handler == Null || Is<JSReceiver>(proxy.handler));
const handler = const handler =
Cast<JSReceiver>(proxy.handler) otherwise ThrowProxyHandlerRevoked; Cast<JSReceiver>(proxy.handler) otherwise ThrowProxyHandlerRevoked;
......
...@@ -30,21 +30,20 @@ namespace proxy { ...@@ -30,21 +30,20 @@ namespace proxy {
return Undefined; return Undefined;
} }
// 2. Let handler be O.[[ProxyHandler]].
const handler: Object = proxy.handler;
try { try {
// 2. Let handler be O.[[ProxyHandler]].
// 3. If handler is null, throw a TypeError exception. // 3. If handler is null, throw a TypeError exception.
// 4. Assert: Type(handler) is Object. // 4. Assert: Type(handler) is Object.
const handlerJSReceiver = assert(proxy.handler == Null || Is<JSReceiver>(proxy.handler));
Cast<JSReceiver>(handler) otherwise ThrowProxyHandlerRevoked; const handler =
Cast<JSReceiver>(proxy.handler) otherwise ThrowProxyHandlerRevoked;
// 5. Let target be O.[[ProxyTarget]]. // 5. Let target be O.[[ProxyTarget]].
const target = UnsafeCast<JSReceiver>(proxy.target); const target = UnsafeCast<JSReceiver>(proxy.target);
// 6. Let trap be ? GetMethod(handler, "set"). // 6. Let trap be ? GetMethod(handler, "set").
// 7. If trap is undefined, then (see 7.a below). // 7. If trap is undefined, then (see 7.a below).
const trap: Callable = GetMethod(handlerJSReceiver, 'set') const trap: Callable = GetMethod(handler, 'set')
otherwise goto TrapUndefined(target); otherwise goto TrapUndefined(target);
// 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler,
...@@ -61,8 +60,8 @@ namespace proxy { ...@@ -61,8 +60,8 @@ namespace proxy {
// i. If targetDesc.[[Set]] is undefined, throw a TypeError // i. If targetDesc.[[Set]] is undefined, throw a TypeError
// exception. // exception.
// 12. Return true. // 12. Return true.
const trapResult = Call( const trapResult =
context, trap, handlerJSReceiver, target, name, value, receiverValue); Call(context, trap, handler, target, name, value, receiverValue);
if (BranchIfToBooleanIsTrue(trapResult)) { if (BranchIfToBooleanIsTrue(trapResult)) {
CheckGetSetTrapResult(target, proxy, name, value, kProxySet); CheckGetSetTrapResult(target, proxy, name, value, kProxySet);
return value; return value;
...@@ -77,7 +76,6 @@ namespace proxy { ...@@ -77,7 +76,6 @@ namespace proxy {
return value; return value;
} }
label ThrowProxyHandlerRevoked deferred { label ThrowProxyHandlerRevoked deferred {
assert(handler == Null);
ThrowTypeError(kProxyRevoked, 'set'); ThrowTypeError(kProxyRevoked, 'set');
} }
} }
......
// Copyright 2019 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.
#include 'src/builtins/builtins-proxy-gen.h'
namespace proxy {
// ES #sec-proxy-object-internal-methods-and-internal-slots-setprototypeof-v
// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-setprototypeof-v
transitioning builtin
ProxySetPrototypeOf(implicit context: Context)(
proxy: JSProxy, proto: Object, doThrow: Boolean): Object {
PerformStackCheck();
const kTrapName: constexpr string = 'setPrototypeOf';
try {
// 1. Assert: Either Type(V) is Object or Type(V) is Null.
assert(proto == Null || Is<JSReceiver>(proto));
// 2. Let handler be O.[[ProxyHandler]].
// 3. If handler is null, throw a TypeError exception.
// 4. Assert: Type(handler) is Object.
assert(proxy.handler == Null || Is<JSReceiver>(proxy.handler));
const handler =
Cast<JSReceiver>(proxy.handler) otherwise ThrowProxyHandlerRevoked;
// 5. Let target be O.[[ProxyTarget]].
const target = proxy.target;
// 6. Let trap be ? GetMethod(handler, "setPrototypeOf").
// 7. If trap is undefined, then (see 7.a below).
const trap: Callable = GetMethod(handler, kTrapName)
otherwise goto TrapUndefined(target, proto);
// 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, « target, V
// »)).
const trapResult = Call(context, trap, handler, target, proto);
// 9. If booleanTrapResult is false, return false.
if (BranchIfToBooleanIsFalse(trapResult)) {
if (doThrow == True) {
ThrowTypeError(kProxyTrapReturnedFalsishFor, kTrapName);
}
return False;
}
// 10. Let extensibleTarget be ? IsExtensible(target).
// 11. If extensibleTarget is true, return true.
const extensibleTarget: Object = object::ObjectIsExtensible(target);
assert(extensibleTarget == True || extensibleTarget == False);
if (extensibleTarget == True) {
return True;
}
// 12. Let targetProto be ? target.[[GetPrototypeOf]]().
const targetProto = object::ObjectGetPrototypeOf(target);
// 13. If SameValue(V, targetProto) is false, throw a TypeError
// exception.
// 14. Return true.
if (BranchIfSameValue(proto, targetProto)) {
return True;
}
ThrowTypeError(kProxySetPrototypeOfNonExtensible);
}
label TrapUndefined(target: Object, proto: Object) {
// 7.a. Return ? target.[[SetPrototypeOf]]().
if (doThrow == True) {
return object::ObjectSetPrototypeOfThrow(target, proto);
}
return object::ObjectSetPrototypeOfDontThrow(target, proto);
}
label ThrowProxyHandlerRevoked deferred {
ThrowTypeError(kProxyRevoked, kTrapName);
}
}
}
...@@ -42,6 +42,8 @@ namespace proxy { ...@@ -42,6 +42,8 @@ namespace proxy {
generates 'MessageTemplate::kProxyGetPrototypeOfInvalid'; generates 'MessageTemplate::kProxyGetPrototypeOfInvalid';
const kProxyGetPrototypeOfNonExtensible: constexpr MessageTemplate const kProxyGetPrototypeOfNonExtensible: constexpr MessageTemplate
generates 'MessageTemplate::kProxyGetPrototypeOfNonExtensible'; generates 'MessageTemplate::kProxyGetPrototypeOfNonExtensible';
const kProxySetPrototypeOfNonExtensible: constexpr MessageTemplate
generates 'MessageTemplate::kProxySetPrototypeOfNonExtensible';
const kProxyGet: constexpr int31 const kProxyGet: constexpr int31
generates 'JSProxy::AccessKind::kGet'; generates 'JSProxy::AccessKind::kGet';
......
...@@ -30,4 +30,16 @@ namespace reflect { ...@@ -30,4 +30,16 @@ namespace reflect {
otherwise ThrowTypeError(kCalledOnNonObject, 'Reflect.getPrototypeOf'); otherwise ThrowTypeError(kCalledOnNonObject, 'Reflect.getPrototypeOf');
return object::JSReceiverGetPrototypeOf(objectJSReceiver); return object::JSReceiverGetPrototypeOf(objectJSReceiver);
} }
// ES6 section 26.1.14 Reflect.setPrototypeOf
transitioning javascript builtin ReflectSetPrototypeOf(
js-implicit context:
Context)(_receiver: Object, object: Object, proto: Object): Object {
const objectJSReceiver = Cast<JSReceiver>(object)
otherwise ThrowTypeError(kCalledOnNonObject, 'Reflect.setPrototypeOf');
if (proto == Null || Is<JSReceiver>(proto)) {
return object::ObjectSetPrototypeOfDontThrow(objectJSReceiver, proto);
}
ThrowTypeError(kProtoObjectOrNull, proto);
}
} // namespace reflect } // namespace reflect
...@@ -796,6 +796,12 @@ class V8_EXPORT_PRIVATE CodeStubAssembler ...@@ -796,6 +796,12 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
// otherwise goes to {if_false}. // otherwise goes to {if_false}.
void BranchIfToBooleanIsTrue(Node* value, Label* if_true, Label* if_false); void BranchIfToBooleanIsTrue(Node* value, Label* if_true, Label* if_false);
// Branches to {if_false} if ToBoolean applied to {value} yields false,
// otherwise goes to {if_true}.
void BranchIfToBooleanIsFalse(Node* value, Label* if_false, Label* if_true) {
BranchIfToBooleanIsTrue(value, if_true, if_false);
}
void BranchIfJSReceiver(Node* object, Label* if_true, Label* if_false); void BranchIfJSReceiver(Node* object, Label* if_true, Label* if_false);
// Branches to {if_true} when --force-slow-path flag has been passed. // Branches to {if_true} when --force-slow-path flag has been passed.
......
...@@ -1449,7 +1449,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object, ...@@ -1449,7 +1449,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
Builtins::kObjectGetPrototypeOf, 1, true); Builtins::kObjectGetPrototypeOf, 1, true);
native_context()->set_object_get_prototype_of(*object_get_prototype_of); native_context()->set_object_get_prototype_of(*object_get_prototype_of);
SimpleInstallFunction(isolate_, object_function, "setPrototypeOf", SimpleInstallFunction(isolate_, object_function, "setPrototypeOf",
Builtins::kObjectSetPrototypeOf, 2, false); Builtins::kObjectSetPrototypeOf, 2, true);
SimpleInstallFunction(isolate_, object_function, "isExtensible", SimpleInstallFunction(isolate_, object_function, "isExtensible",
Builtins::kObjectIsExtensible, 1, true); Builtins::kObjectIsExtensible, 1, true);
......
...@@ -546,6 +546,32 @@ RUNTIME_FUNCTION(Runtime_JSReceiverGetPrototypeOf) { ...@@ -546,6 +546,32 @@ RUNTIME_FUNCTION(Runtime_JSReceiverGetPrototypeOf) {
JSReceiver::GetPrototype(isolate, receiver)); JSReceiver::GetPrototype(isolate, receiver));
} }
RUNTIME_FUNCTION(Runtime_JSReceiverSetPrototypeOfThrow) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, proto, 1);
MAYBE_RETURN(JSReceiver::SetPrototype(object, proto, true, kThrowOnError),
ReadOnlyRoots(isolate).exception());
return *object;
}
RUNTIME_FUNCTION(Runtime_JSReceiverSetPrototypeOfDontThrow) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, proto, 1);
Maybe<bool> result =
JSReceiver::SetPrototype(object, proto, true, kDontThrow);
MAYBE_RETURN(result, ReadOnlyRoots(isolate).exception());
return *isolate->factory()->ToBoolean(result.FromJust());
}
RUNTIME_FUNCTION(Runtime_GetProperty) { RUNTIME_FUNCTION(Runtime_GetProperty) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(2, args.length()); DCHECK_EQ(2, args.length());
......
...@@ -303,6 +303,8 @@ namespace internal { ...@@ -303,6 +303,8 @@ namespace internal {
F(JSReceiverPreventExtensionsDontThrow, 1, 1) \ F(JSReceiverPreventExtensionsDontThrow, 1, 1) \
F(JSReceiverPreventExtensionsThrow, 1, 1) \ F(JSReceiverPreventExtensionsThrow, 1, 1) \
F(JSReceiverGetPrototypeOf, 1, 1) \ F(JSReceiverGetPrototypeOf, 1, 1) \
F(JSReceiverSetPrototypeOfDontThrow, 2, 1) \
F(JSReceiverSetPrototypeOfThrow, 2, 1) \
F(NewObject, 2, 1) \ F(NewObject, 2, 1) \
F(ObjectCreate, 2, 1) \ F(ObjectCreate, 2, 1) \
F(ObjectEntries, 1, 1) \ F(ObjectEntries, 1, 1) \
......
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