From f2af839b1938b55b4d32a2a1eb6704c49c8d877d Mon Sep 17 00:00:00 2001 From: Maya Lekova Date: Mon, 10 Jul 2017 13:42:33 +0200 Subject: [PATCH] [builtins] Port Proxy constructor to CSA. Rename builtins-proxy.cc to builtins-proxy-gen.cc. Bug: v8:6557, v8:6567 Change-Id: I0e52a0c0c6c9b307c33bb18ec36079bdfd4a89ef Reviewed-on: https://chromium-review.googlesource.com/565278 Commit-Queue: Maya Lekova Reviewed-by: Benedikt Meurer Cr-Commit-Position: refs/heads/master@{#46511} --- BUILD.gn | 2 +- src/builtins/builtins-definitions.h | 5 +- src/builtins/builtins-proxy-gen.cc | 139 ++++++++++++++++++++++++ src/builtins/builtins-proxy.cc | 33 ------ src/code-stub-assembler.cc | 9 +- src/code-stub-assembler.h | 1 + src/v8.gyp | 2 +- test/mjsunit/es6/proxies-constructor.js | 47 ++++++++ 8 files changed, 200 insertions(+), 38 deletions(-) create mode 100644 src/builtins/builtins-proxy-gen.cc delete mode 100644 src/builtins/builtins-proxy.cc diff --git a/BUILD.gn b/BUILD.gn index c0c62130ed..cd0f3a3203 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -972,6 +972,7 @@ v8_source_set("v8_builtins_generators") { "src/builtins/builtins-object-gen.cc", "src/builtins/builtins-promise-gen.cc", "src/builtins/builtins-promise-gen.h", + "src/builtins/builtins-proxy-gen.cc", "src/builtins/builtins-regexp-gen.cc", "src/builtins/builtins-regexp-gen.h", "src/builtins/builtins-sharedarraybuffer-gen.cc", @@ -1206,7 +1207,6 @@ v8_source_set("v8_base") { "src/builtins/builtins-math.cc", "src/builtins/builtins-number.cc", "src/builtins/builtins-object.cc", - "src/builtins/builtins-proxy.cc", "src/builtins/builtins-reflect.cc", "src/builtins/builtins-regexp.cc", "src/builtins/builtins-sharedarraybuffer.cc", diff --git a/src/builtins/builtins-definitions.h b/src/builtins/builtins-definitions.h index 6c144602cc..62a44d363d 100644 --- a/src/builtins/builtins-definitions.h +++ b/src/builtins/builtins-definitions.h @@ -791,8 +791,9 @@ namespace internal { TFJ(PromiseRace, 1, kIterable) \ \ /* Proxy */ \ - CPP(ProxyConstructor) \ - CPP(ProxyConstructor_ConstructStub) \ + TFJ(ProxyConstructor, 0) \ + TFJ(ProxyConstructor_ConstructStub, \ + SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ \ /* Reflect */ \ ASM(ReflectApply) \ diff --git a/src/builtins/builtins-proxy-gen.cc b/src/builtins/builtins-proxy-gen.cc new file mode 100644 index 0000000000..6ae65ac694 --- /dev/null +++ b/src/builtins/builtins-proxy-gen.cc @@ -0,0 +1,139 @@ +// Copyright 2016 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-utils-gen.h" +#include "src/builtins/builtins-utils.h" +#include "src/builtins/builtins.h" +#include "src/code-stub-assembler.h" + +#include "src/counters.h" +#include "src/objects-inl.h" + +namespace v8 { +namespace internal { +using compiler::Node; +using compiler::CodeAssembler; + +// ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Call]] case. +TF_BUILTIN(ProxyConstructor, CodeStubAssembler) { + Node* context = Parameter(Descriptor::kContext); + + CallRuntime(Runtime::kThrowTypeError, context, + SmiConstant(MessageTemplate::kConstructorNotFunction), + CStringConstant("Proxy")); + Unreachable(); +} + +class ProxiesCodeStubAssembler : public CodeStubAssembler { + public: + explicit ProxiesCodeStubAssembler(compiler::CodeAssemblerState* state) + : CodeStubAssembler(state) {} + + Node* IsProxyRevoked(Node* proxy) { + CSA_ASSERT(this, IsJSProxy(proxy)); + + Node* handler = LoadObjectField(proxy, JSProxy::kHandlerOffset); + CSA_ASSERT(this, Word32Or(IsJSReceiver(handler), IsNull(handler))); + + return IsNull(handler); + } + + void GotoIfProxyRevoked(Node* object, Label* if_proxy_revoked) { + Label continue_checks(this); + GotoIfNot(IsJSProxy(object), &continue_checks); + GotoIf(IsProxyRevoked(object), if_proxy_revoked); + Goto(&continue_checks); + BIND(&continue_checks); + } + + Node* AllocateProxy(Node* target, Node* handler, Node* context) { + VARIABLE(map, MachineRepresentation::kTagged); + + Label callable_target(this), constructor_target(this), none_target(this), + create_proxy(this); + + Node* nativeContext = LoadNativeContext(context); + + GotoIf(IsCallable(target), &callable_target); + Goto(&none_target); + + BIND(&callable_target); + { + // Every object that is a constructor is implicitly callable + // so it's okay to nest this check here + GotoIf(IsConstructor(target), &constructor_target); + map.Bind( + LoadContextElement(nativeContext, Context::PROXY_CALLABLE_MAP_INDEX)); + Goto(&create_proxy); + } + BIND(&constructor_target); + { + map.Bind(LoadContextElement(nativeContext, + Context::PROXY_CONSTRUCTOR_MAP_INDEX)); + Goto(&create_proxy); + } + BIND(&none_target); + { + map.Bind(LoadContextElement(nativeContext, Context::PROXY_MAP_INDEX)); + Goto(&create_proxy); + } + + BIND(&create_proxy); + Node* proxy = Allocate(JSProxy::kSize); + StoreMapNoWriteBarrier(proxy, map.value()); + StoreObjectFieldRoot(proxy, JSProxy::kPropertiesOffset, + Heap::kEmptyPropertiesDictionaryRootIndex); + StoreObjectFieldNoWriteBarrier(proxy, JSProxy::kTargetOffset, target); + StoreObjectFieldNoWriteBarrier(proxy, JSProxy::kHandlerOffset, handler); + StoreObjectFieldNoWriteBarrier(proxy, JSProxy::kHashOffset, + UndefinedConstant()); + + return proxy; + } +}; + +// ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Construct]] case. +TF_BUILTIN(ProxyConstructor_ConstructStub, ProxiesCodeStubAssembler) { + int const kTargetArg = 0; + int const kHandlerArg = 1; + + Node* argc = + ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount)); + CodeStubArguments args(this, argc); + + Node* target = args.GetOptionalArgumentValue(kTargetArg); + Node* handler = args.GetOptionalArgumentValue(kHandlerArg); + Node* context = Parameter(BuiltinDescriptor::kContext); + + Label throw_proxy_non_object(this, Label::kDeferred), + throw_proxy_handler_or_target_revoked(this, Label::kDeferred), + return_create_proxy(this); + + GotoIf(TaggedIsSmi(target), &throw_proxy_non_object); + GotoIfNot(IsJSReceiver(target), &throw_proxy_non_object); + GotoIfProxyRevoked(target, &throw_proxy_handler_or_target_revoked); + + GotoIf(TaggedIsSmi(handler), &throw_proxy_non_object); + GotoIfNot(IsJSReceiver(handler), &throw_proxy_non_object); + GotoIfProxyRevoked(handler, &throw_proxy_handler_or_target_revoked); + + args.PopAndReturn(AllocateProxy(target, handler, context)); + + BIND(&throw_proxy_non_object); + { + CallRuntime(Runtime::kThrowTypeError, context, + SmiConstant(MessageTemplate::kProxyNonObject)); + Unreachable(); + } + + BIND(&throw_proxy_handler_or_target_revoked); + { + CallRuntime(Runtime::kThrowTypeError, context, + SmiConstant(MessageTemplate::kProxyHandlerOrTargetRevoked)); + Unreachable(); + } +} + +} // namespace internal +} // namespace v8 diff --git a/src/builtins/builtins-proxy.cc b/src/builtins/builtins-proxy.cc deleted file mode 100644 index db6f7b57c9..0000000000 --- a/src/builtins/builtins-proxy.cc +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2016 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.h" -#include "src/builtins/builtins-utils.h" - -#include "src/counters.h" -#include "src/objects-inl.h" - -namespace v8 { -namespace internal { - -// ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Call]] case. -BUILTIN(ProxyConstructor) { - HandleScope scope(isolate); - THROW_NEW_ERROR_RETURN_FAILURE( - isolate, - NewTypeError(MessageTemplate::kConstructorNotFunction, - isolate->factory()->NewStringFromAsciiChecked("Proxy"))); -} - -// ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Construct]] case. -BUILTIN(ProxyConstructor_ConstructStub) { - HandleScope scope(isolate); - DCHECK(isolate->proxy_function()->IsConstructor()); - Handle target = args.atOrUndefined(isolate, 1); - Handle handler = args.atOrUndefined(isolate, 2); - RETURN_RESULT_OR_FAILURE(isolate, JSProxy::New(isolate, target, handler)); -} - -} // namespace internal -} // namespace v8 diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc index 6d33f79e55..4fbfb4a8a9 100644 --- a/src/code-stub-assembler.cc +++ b/src/code-stub-assembler.cc @@ -3070,7 +3070,7 @@ Node* CodeStubAssembler::ToThisValue(Node* context, Node* value, ? &done_loop : &done_throw); - // Load the mape of the {value}. + // Load the map of the {value}. Node* value_map = LoadMap(value); // Load the instance type of the {value}. @@ -3298,6 +3298,13 @@ Node* CodeStubAssembler::IsJSObject(Node* object) { return IsJSObjectMap(LoadMap(object)); } +Node* CodeStubAssembler::IsJSProxy(Node* object) { + Node* object_map = LoadMap(object); + Node* object_instance_type = LoadMapInstanceType(object_map); + + return InstanceTypeEqual(object_instance_type, JS_PROXY_TYPE); +} + Node* CodeStubAssembler::IsJSGlobalProxy(Node* object) { return Word32Equal(LoadInstanceType(object), Int32Constant(JS_GLOBAL_PROXY_TYPE)); diff --git a/src/code-stub-assembler.h b/src/code-stub-assembler.h index 303980bacb..105b4a2de5 100644 --- a/src/code-stub-assembler.h +++ b/src/code-stub-assembler.h @@ -805,6 +805,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { Node* IsJSGlobalProxy(Node* object); Node* IsJSObjectMap(Node* map); Node* IsJSObject(Node* object); + Node* IsJSProxy(Node* object); Node* IsJSReceiverInstanceType(Node* instance_type); Node* IsJSReceiverMap(Node* map); Node* IsJSReceiver(Node* object); diff --git a/src/v8.gyp b/src/v8.gyp index 4d8cbb9988..ef4ede3386 100644 --- a/src/v8.gyp +++ b/src/v8.gyp @@ -207,6 +207,7 @@ 'builtins/builtins-object-gen.cc', 'builtins/builtins-promise-gen.cc', 'builtins/builtins-promise-gen.h', + 'builtins/builtins-proxy-gen.cc', 'builtins/builtins-regexp-gen.cc', 'builtins/builtins-regexp-gen.h', 'builtins/builtins-sharedarraybuffer-gen.cc', @@ -645,7 +646,6 @@ 'builtins/builtins-math.cc', 'builtins/builtins-number.cc', 'builtins/builtins-object.cc', - 'builtins/builtins-proxy.cc', 'builtins/builtins-reflect.cc', 'builtins/builtins-regexp.cc', 'builtins/builtins-sharedarraybuffer.cc', diff --git a/test/mjsunit/es6/proxies-constructor.js b/test/mjsunit/es6/proxies-constructor.js index 4da8a09775..5b30725a52 100644 --- a/test/mjsunit/es6/proxies-constructor.js +++ b/test/mjsunit/es6/proxies-constructor.js @@ -47,3 +47,50 @@ assertThrows(function(){ new Proxy({}, revocable.proxy); }, TypeError); })(); + + +(function testConstructionWithoutArguments() { + assertThrows(function(){ new Proxy(); }, TypeError); + + assertThrows(function(){ new Proxy(42); }, TypeError); + + assertThrows(function(){ new Proxy({}); }, TypeError); +})(); + + +(function testConstructionFromArray() { + var p = new Proxy([42], {}); + assertTrue(p instanceof Array); + assertEquals(p[0], 42); +})(); + + +(function testConstructionFromObject() { + var p = new Proxy({ + prop: 42 + }, {}); + assertTrue(p instanceof Object); + assertEquals(p.prop, 42); +})(); + + +(function testConstructionFromCallable() { + var p = new Proxy(() => { return 42; }, {}); + assertTrue(p instanceof Function); + assertEquals(p(), 42); +})(); + + +(function testConstructionFromConstructor() { + class foo {}; + var p = new Proxy(foo, {}); + assertTrue(p instanceof Function); + assertTrue(new p() instanceof foo); +})(); + + +(function testConstructionFromProxy() { + var q = new Proxy({}, {}); + var p = new Proxy(q, {}); + assertTrue(p instanceof Object); +})();