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: Jakob Gruber <jgruber@chromium.org> Reviewed-by: Maya Lekova <mslekova@chromium.org> Cr-Commit-Position: refs/heads/master@{#62402}
This commit is contained in:
parent
9f8561be3d
commit
fc8c4ef27e
1
BUILD.gn
1
BUILD.gn
@ -964,6 +964,7 @@ torque_files = [
|
||||
"src/builtins/proxy-revocable.tq",
|
||||
"src/builtins/proxy-revoke.tq",
|
||||
"src/builtins/proxy-set-property.tq",
|
||||
"src/builtins/proxy-set-prototype-of.tq",
|
||||
"src/builtins/proxy.tq",
|
||||
"src/builtins/reflect.tq",
|
||||
"src/builtins/regexp-replace.tq",
|
||||
|
@ -1006,6 +1006,8 @@ const kCalledNonCallable: constexpr MessageTemplate
|
||||
generates 'MessageTemplate::kCalledNonCallable';
|
||||
const kCalledOnNullOrUndefined: constexpr MessageTemplate
|
||||
generates 'MessageTemplate::kCalledOnNullOrUndefined';
|
||||
const kProtoObjectOrNull: constexpr MessageTemplate
|
||||
generates 'MessageTemplate::kProtoObjectOrNull';
|
||||
const kInvalidOffset: constexpr MessageTemplate
|
||||
generates 'MessageTemplate::kInvalidOffset';
|
||||
const kInvalidTypedArrayLength: constexpr MessageTemplate
|
||||
@ -2834,6 +2836,8 @@ macro NumberIsNaN(number: Number): bool {
|
||||
extern macro GotoIfForceSlowPath() labels Taken;
|
||||
extern macro BranchIfToBooleanIsTrue(Object): never
|
||||
labels Taken, NotTaken;
|
||||
extern macro BranchIfToBooleanIsFalse(Object): never
|
||||
labels Taken, NotTaken;
|
||||
|
||||
macro ToBoolean(obj: Object): bool {
|
||||
if (BranchIfToBooleanIsTrue(obj)) {
|
||||
|
@ -726,7 +726,6 @@ namespace internal {
|
||||
CPP(ObjectGetOwnPropertyDescriptors) \
|
||||
TFJ(ObjectGetOwnPropertyNames, 1, kReceiver, kObject) \
|
||||
CPP(ObjectGetOwnPropertySymbols) \
|
||||
CPP(ObjectSetPrototypeOf) \
|
||||
TFJ(ObjectIs, 2, kReceiver, kLeft, kRight) \
|
||||
CPP(ObjectIsFrozen) \
|
||||
CPP(ObjectIsSealed) \
|
||||
@ -826,7 +825,6 @@ namespace internal {
|
||||
TFJ(ReflectHas, 2, kReceiver, kTarget, kKey) \
|
||||
CPP(ReflectOwnKeys) \
|
||||
CPP(ReflectSet) \
|
||||
CPP(ReflectSetPrototypeOf) \
|
||||
\
|
||||
/* RegExp */ \
|
||||
CPP(RegExpCapture1Getter) \
|
||||
|
@ -218,39 +218,6 @@ BUILTIN(ObjectFreeze) {
|
||||
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__
|
||||
BUILTIN(ObjectPrototypeGetProto) {
|
||||
HandleScope scope(isolate);
|
||||
|
@ -168,30 +168,5 @@ BUILTIN(ReflectSet) {
|
||||
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 v8
|
||||
|
@ -16,6 +16,14 @@ namespace runtime {
|
||||
|
||||
extern transitioning runtime
|
||||
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 object {
|
||||
@ -34,7 +42,7 @@ namespace object {
|
||||
const objectJSProxy = Cast<JSProxy>(objectJSReceiver)
|
||||
otherwise return runtime::JSReceiverPreventExtensionsThrow(
|
||||
objectJSReceiver);
|
||||
const _status: Object = proxy::ProxyPreventExtensions(objectJSProxy, True);
|
||||
proxy::ProxyPreventExtensions(objectJSProxy, True);
|
||||
return objectJSReceiver;
|
||||
}
|
||||
|
||||
@ -61,6 +69,27 @@ namespace object {
|
||||
otherwise return runtime::JSReceiverGetPrototypeOf(object);
|
||||
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_isextensible {
|
||||
@ -86,3 +115,25 @@ namespace object_getprototypeof {
|
||||
return object::ObjectGetPrototypeOf(object);
|
||||
}
|
||||
} // 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 {
|
||||
// 1. Let handler be O.[[ProxyHandler]].
|
||||
// 2. If handler is null, throw a TypeError exception.
|
||||
// 3. Assert: Type(handler) is Object.
|
||||
assert(proxy.handler == Null || Is<JSReceiver>(proxy.handler));
|
||||
const handler =
|
||||
Cast<JSReceiver>(proxy.handler) otherwise ThrowProxyHandlerRevoked;
|
||||
|
||||
|
@ -22,6 +22,7 @@ namespace proxy {
|
||||
// 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;
|
||||
|
||||
|
@ -16,6 +16,7 @@ namespace proxy {
|
||||
// 1. Let handler be O.[[ProxyHandler]].
|
||||
// 2. If handler is null, throw a TypeError exception.
|
||||
// 3. Assert: Type(handler) is Object.
|
||||
assert(proxy.handler == Null || Is<JSReceiver>(proxy.handler));
|
||||
const handler =
|
||||
Cast<JSReceiver>(proxy.handler) otherwise ThrowProxyHandlerRevoked;
|
||||
|
||||
|
@ -17,6 +17,7 @@ namespace proxy {
|
||||
// 1. Let handler be O.[[ProxyHandler]].
|
||||
// 2. If handler is null, throw a TypeError exception.
|
||||
// 3. Assert: Type(handler) is Object.
|
||||
assert(proxy.handler == Null || Is<JSReceiver>(proxy.handler));
|
||||
const handler =
|
||||
Cast<JSReceiver>(proxy.handler) otherwise ThrowProxyHandlerRevoked;
|
||||
|
||||
|
@ -30,21 +30,20 @@ namespace proxy {
|
||||
return Undefined;
|
||||
}
|
||||
|
||||
// 2. Let handler be O.[[ProxyHandler]].
|
||||
const handler: Object = proxy.handler;
|
||||
|
||||
try {
|
||||
// 2. Let handler be O.[[ProxyHandler]].
|
||||
// 3. If handler is null, throw a TypeError exception.
|
||||
// 4. Assert: Type(handler) is Object.
|
||||
const handlerJSReceiver =
|
||||
Cast<JSReceiver>(handler) otherwise ThrowProxyHandlerRevoked;
|
||||
assert(proxy.handler == Null || Is<JSReceiver>(proxy.handler));
|
||||
const handler =
|
||||
Cast<JSReceiver>(proxy.handler) otherwise ThrowProxyHandlerRevoked;
|
||||
|
||||
// 5. Let target be O.[[ProxyTarget]].
|
||||
const target = UnsafeCast<JSReceiver>(proxy.target);
|
||||
|
||||
// 6. Let trap be ? GetMethod(handler, "set").
|
||||
// 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);
|
||||
|
||||
// 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler,
|
||||
@ -61,8 +60,8 @@ namespace proxy {
|
||||
// i. If targetDesc.[[Set]] is undefined, throw a TypeError
|
||||
// exception.
|
||||
// 12. Return true.
|
||||
const trapResult = Call(
|
||||
context, trap, handlerJSReceiver, target, name, value, receiverValue);
|
||||
const trapResult =
|
||||
Call(context, trap, handler, target, name, value, receiverValue);
|
||||
if (BranchIfToBooleanIsTrue(trapResult)) {
|
||||
CheckGetSetTrapResult(target, proxy, name, value, kProxySet);
|
||||
return value;
|
||||
@ -77,7 +76,6 @@ namespace proxy {
|
||||
return value;
|
||||
}
|
||||
label ThrowProxyHandlerRevoked deferred {
|
||||
assert(handler == Null);
|
||||
ThrowTypeError(kProxyRevoked, 'set');
|
||||
}
|
||||
}
|
||||
|
77
src/builtins/proxy-set-prototype-of.tq
Normal file
77
src/builtins/proxy-set-prototype-of.tq
Normal file
@ -0,0 +1,77 @@
|
||||
// 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 {
|
||||
generates 'MessageTemplate::kProxyGetPrototypeOfInvalid';
|
||||
const kProxyGetPrototypeOfNonExtensible: constexpr MessageTemplate
|
||||
generates 'MessageTemplate::kProxyGetPrototypeOfNonExtensible';
|
||||
const kProxySetPrototypeOfNonExtensible: constexpr MessageTemplate
|
||||
generates 'MessageTemplate::kProxySetPrototypeOfNonExtensible';
|
||||
|
||||
const kProxyGet: constexpr int31
|
||||
generates 'JSProxy::AccessKind::kGet';
|
||||
|
@ -30,4 +30,16 @@ namespace reflect {
|
||||
otherwise ThrowTypeError(kCalledOnNonObject, 'Reflect.getPrototypeOf');
|
||||
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
|
||||
|
@ -796,6 +796,12 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
|
||||
// otherwise goes to {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);
|
||||
|
||||
// Branches to {if_true} when --force-slow-path flag has been passed.
|
||||
|
@ -1449,7 +1449,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
|
||||
Builtins::kObjectGetPrototypeOf, 1, true);
|
||||
native_context()->set_object_get_prototype_of(*object_get_prototype_of);
|
||||
SimpleInstallFunction(isolate_, object_function, "setPrototypeOf",
|
||||
Builtins::kObjectSetPrototypeOf, 2, false);
|
||||
Builtins::kObjectSetPrototypeOf, 2, true);
|
||||
|
||||
SimpleInstallFunction(isolate_, object_function, "isExtensible",
|
||||
Builtins::kObjectIsExtensible, 1, true);
|
||||
|
@ -546,6 +546,32 @@ RUNTIME_FUNCTION(Runtime_JSReceiverGetPrototypeOf) {
|
||||
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) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(2, args.length());
|
||||
|
@ -303,6 +303,8 @@ namespace internal {
|
||||
F(JSReceiverPreventExtensionsDontThrow, 1, 1) \
|
||||
F(JSReceiverPreventExtensionsThrow, 1, 1) \
|
||||
F(JSReceiverGetPrototypeOf, 1, 1) \
|
||||
F(JSReceiverSetPrototypeOfDontThrow, 2, 1) \
|
||||
F(JSReceiverSetPrototypeOfThrow, 2, 1) \
|
||||
F(NewObject, 2, 1) \
|
||||
F(ObjectCreate, 2, 1) \
|
||||
F(ObjectEntries, 1, 1) \
|
||||
|
Loading…
Reference in New Issue
Block a user