Reland of Port Proxy SetProperty trap builtin to Torque

Reverted CL is in https://chromium-review.googlesource.com/c/v8/v8/+/1585269
This includes fix for ThrowTypeErrorIfStrict and add regression test.

Spec: https://tc39.github.io/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver
Bug: v8:6664, v8:9234
Change-Id: I785df3f12f619e2e0fe7b011b72043758e4083e3
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1604071
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Maya Lekova <mslekova@chromium.org>
Commit-Queue: Z Nguyen-Huu <duongn@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#61497}
diff --git a/BUILD.gn b/BUILD.gn
index d67de66..384a947 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -948,6 +948,7 @@
   "src/builtins/object-fromentries.tq",
   "src/builtins/proxy-constructor.tq",
   "src/builtins/proxy-get-property.tq",
+  "src/builtins/proxy-set-property.tq",
   "src/builtins/proxy-revocable.tq",
   "src/builtins/proxy-revoke.tq",
   "src/builtins/proxy.tq",
diff --git a/src/builtins/base.tq b/src/builtins/base.tq
index 63b781a..6d3d3b9 100644
--- a/src/builtins/base.tq
+++ b/src/builtins/base.tq
@@ -1276,6 +1276,9 @@
     constexpr MessageTemplate, Object, Object): never;
 extern macro ThrowTypeError(implicit context: Context)(
     constexpr MessageTemplate, Object, Object, Object): never;
+extern transitioning runtime ThrowTypeErrorIfStrict(implicit context: Context)(
+    Smi, Object, Object): void;
+
 extern macro ArraySpeciesCreate(Context, Object, Number): JSReceiver;
 extern macro ArrayCreate(implicit context: Context)(Number): JSArray;
 extern macro BuildAppendJSArray(
@@ -1894,6 +1897,7 @@
 extern macro Float64Constant(constexpr float64): float64;
 extern macro SmiConstant(constexpr int31): Smi;
 extern macro SmiConstant(constexpr Smi): Smi;
+extern macro SmiConstant(constexpr MessageTemplate): Smi;
 extern macro BoolConstant(constexpr bool): bool;
 extern macro StringConstant(constexpr string): String;
 extern macro LanguageModeConstant(constexpr LanguageMode): LanguageMode;
diff --git a/src/builtins/builtins-definitions.h b/src/builtins/builtins-definitions.h
index f15426b..ec0bcd0 100644
--- a/src/builtins/builtins-definitions.h
+++ b/src/builtins/builtins-definitions.h
@@ -826,7 +826,6 @@
                                                                                \
   /* Proxy */                                                                  \
   TFS(ProxyHasProperty, kProxy, kName)                                         \
-  TFS(ProxySetProperty, kProxy, kName, kValue, kReceiverValue)                 \
                                                                                \
   /* Reflect */                                                                \
   ASM(ReflectApply, Dummy)                                                     \
diff --git a/src/builtins/builtins-proxy-gen.cc b/src/builtins/builtins-proxy-gen.cc
index 4cd0791..53a87e2 100644
--- a/src/builtins/builtins-proxy-gen.cc
+++ b/src/builtins/builtins-proxy-gen.cc
@@ -338,93 +338,6 @@
                  StringConstant("has"), proxy);
 }
 
-TF_BUILTIN(ProxySetProperty, ProxiesCodeStubAssembler) {
-  Node* context = Parameter(Descriptor::kContext);
-  Node* proxy = Parameter(Descriptor::kProxy);
-  Node* name = Parameter(Descriptor::kName);
-  Node* value = Parameter(Descriptor::kValue);
-  Node* receiver = Parameter(Descriptor::kReceiverValue);
-
-  CSA_ASSERT(this, IsJSProxy(proxy));
-
-  // 1. Assert: IsPropertyKey(P) is true.
-  CSA_ASSERT(this, TaggedIsNotSmi(name));
-  CSA_ASSERT(this, IsName(name));
-
-  Label throw_proxy_handler_revoked(this, Label::kDeferred),
-      trap_undefined(this), failure(this, Label::kDeferred),
-      continue_checks(this), success(this),
-      private_symbol(this, Label::kDeferred);
-
-  GotoIf(IsPrivateSymbol(name), &private_symbol);
-
-  // 2. Let handler be O.[[ProxyHandler]].
-  Node* handler = LoadObjectField(proxy, JSProxy::kHandlerOffset);
-
-  // 3. If handler is null, throw a TypeError exception.
-  GotoIfNot(IsJSReceiver(handler), &throw_proxy_handler_revoked);
-
-  // 4. Assert: Type(handler) is Object.
-  CSA_ASSERT(this, IsJSReceiver(handler));
-
-  // 5. Let target be O.[[ProxyTarget]].
-  Node* target = LoadObjectField(proxy, JSProxy::kTargetOffset);
-
-  // 6. Let trap be ? GetMethod(handler, "set").
-  // 7. If trap is undefined, then (see 7.a below).
-  Handle<Name> set_string = factory()->set_string();
-  Node* trap = GetMethod(context, handler, set_string, &trap_undefined);
-
-  // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler,
-  // « target, P, V, Receiver »)).
-  // 9. If booleanTrapResult is false, return false.
-  BranchIfToBooleanIsTrue(
-      CallJS(CodeFactory::Call(isolate(),
-                               ConvertReceiverMode::kNotNullOrUndefined),
-             context, trap, handler, target, name, value, receiver),
-      &continue_checks, &failure);
-
-  BIND(&continue_checks);
-  {
-    // 9. Let targetDesc be ? target.[[GetOwnProperty]](P).
-    Label return_result(this);
-    Return(CheckGetSetTrapResult(context, target, proxy, name, value,
-                                 JSProxy::kSet));
-  }
-
-  BIND(&failure);
-  {
-    CallRuntime(Runtime::kThrowTypeErrorIfStrict, context,
-                SmiConstant(MessageTemplate::kProxyTrapReturnedFalsishFor),
-                HeapConstant(set_string), name);
-    Goto(&success);
-  }
-
-  // 12. Return true.
-  BIND(&success);
-  Return(value);
-
-  BIND(&private_symbol);
-  {
-    Label failure(this);
-
-    CallRuntime(Runtime::kThrowTypeErrorIfStrict, context,
-                SmiConstant(MessageTemplate::kProxyPrivate));
-    Return(UndefinedConstant());
-  }
-
-  BIND(&trap_undefined);
-  {
-    // 7.a. Return ? target.[[Set]](P, V, Receiver).
-    CallRuntime(Runtime::kSetPropertyWithReceiver, context, target, name, value,
-                receiver);
-    Return(value);
-  }
-
-  BIND(&throw_proxy_handler_revoked);
-  ThrowTypeError(context, MessageTemplate::kProxyRevoked, "set");
-}
-
 Node* ProxiesCodeStubAssembler::CheckGetSetTrapResult(
     Node* context, Node* target, Node* proxy, Node* name, Node* trap_result,
     JSProxy::AccessKind access_kind) {
diff --git a/src/builtins/builtins-proxy-gen.h b/src/builtins/builtins-proxy-gen.h
index 34e1473..e8fd006 100644
--- a/src/builtins/builtins-proxy-gen.h
+++ b/src/builtins/builtins-proxy-gen.h
@@ -18,16 +18,6 @@
   explicit ProxiesCodeStubAssembler(compiler::CodeAssemblerState* state)
       : CodeStubAssembler(state) {}
 
-  // ES6 section 9.5.8 [[Get]] ( P, Receiver )
-  // name should not be an index.
-  Node* ProxyGetProperty(Node* context, Node* proxy, Node* name,
-                         Node* receiver);
-
-  // ES6 section 9.5.9 [[Set]] ( P, V, Receiver )
-  // name should not be an index.
-  Node* ProxySetProperty(Node* context, Node* proxy, Node* name, Node* value,
-                         Node* receiver);
-
   Node* AllocateProxy(Node* target, Node* handler, Node* context);
   Node* AllocateProxyRevokeFunction(Node* proxy, Node* context);
 
diff --git a/src/builtins/proxy-get-property.tq b/src/builtins/proxy-get-property.tq
index 453137b..0915a66 100644
--- a/src/builtins/proxy-get-property.tq
+++ b/src/builtins/proxy-get-property.tq
@@ -10,10 +10,6 @@
   GetPropertyWithReceiver(implicit context: Context)(Object, Name, Object, Smi):
       Object;
 
-  extern transitioning macro ProxiesCodeStubAssembler::CheckGetSetTrapResult(
-      implicit context:
-          Context)(Object, JSProxy, Name, Object, constexpr int31): Object;
-
   // ES #sec-proxy-object-internal-methods-and-internal-slots-get-p-receiver
   // https://tc39.github.io/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-get-p-receiver
   transitioning builtin
diff --git a/src/builtins/proxy-set-property.tq b/src/builtins/proxy-set-property.tq
new file mode 100644
index 0000000..72181e0
--- /dev/null
+++ b/src/builtins/proxy-set-property.tq
@@ -0,0 +1,84 @@
+// 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 {
+
+  extern transitioning runtime
+  SetPropertyWithReceiver(implicit context:
+                              Context)(Object, Name, Object, Object): void;
+
+  transitioning macro CallThrowTypeErrorIfStrict(implicit context: Context)(
+      message: constexpr MessageTemplate) {
+    ThrowTypeErrorIfStrict(SmiConstant(message), Null, Null);
+  }
+
+  // ES #sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver
+  // https://tc39.github.io/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver
+  transitioning builtin
+  ProxySetProperty(implicit context: Context)(
+      proxy: JSProxy, name: Name, value: Object,
+      receiverValue: Object): Object {
+    // 1. Assert: IsPropertyKey(P) is true.
+    assert(TaggedIsNotSmi(name));
+    assert(IsName(name));
+
+    if (IsPrivateSymbol(name)) {
+      CallThrowTypeErrorIfStrict(kProxyPrivate);
+      return Undefined;
+    }
+
+    // 2. Let handler be O.[[ProxyHandler]].
+    const handler: Object = proxy.handler;
+
+    try {
+      // 3. If handler is null, throw a TypeError exception.
+      // 4. Assert: Type(handler) is Object.
+      const handlerJSReceiver =
+          Cast<JSReceiver>(handler) otherwise ThrowProxyHandlerRevoked;
+
+      // 5. Let target be O.[[ProxyTarget]].
+      const target = 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')
+          otherwise goto TrapUndefined(target);
+
+      // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler,
+      // « target, P, V, Receiver »)).
+      // 9. If booleanTrapResult is false, return false.
+      // 10. Let targetDesc be ? target.[[GetOwnProperty]](P).
+      // 11. If targetDesc is not undefined and targetDesc.[[Configurable]] is
+      // false, then
+      //    a. If IsDataDescriptor(targetDesc) is true and
+      //    targetDesc.[[Writable]] is false, then
+      //      i. If SameValue(V, targetDesc.[[Value]]) is false, throw a
+      //      TypeError exception.
+      //    b. If IsAccessorDescriptor(targetDesc) is true, then
+      //      i. If targetDesc.[[Set]] is undefined, throw a TypeError
+      //      exception.
+      // 12. Return true.
+      const trapResult = Call(
+          context, trap, handlerJSReceiver, target, name, value, receiverValue);
+      if (BranchIfToBooleanIsTrue(trapResult)) {
+        return CheckGetSetTrapResult(
+            target, proxy, name, trapResult, kProxySet);
+      }
+      ThrowTypeErrorIfStrict(
+          SmiConstant(kProxyTrapReturnedFalsishFor), 'set', name);
+      return value;
+    }
+    label TrapUndefined(target: Object) {
+      // 7.a. Return ? target.[[Set]](P, V, Receiver).
+      SetPropertyWithReceiver(target, name, value, receiverValue);
+      return value;
+    }
+    label ThrowProxyHandlerRevoked deferred {
+      assert(handler == Null);
+      ThrowTypeError(kProxyRevoked, 'set');
+    }
+  }
+}
diff --git a/src/builtins/proxy.tq b/src/builtins/proxy.tq
index a599111..be99917 100644
--- a/src/builtins/proxy.tq
+++ b/src/builtins/proxy.tq
@@ -20,12 +20,20 @@
     return false;
   }
 
+  extern transitioning macro ProxiesCodeStubAssembler::CheckGetSetTrapResult(
+      implicit context:
+          Context)(Object, JSProxy, Name, Object, constexpr int31): Object;
+
   const kProxyNonObject: constexpr MessageTemplate
   generates 'MessageTemplate::kProxyNonObject';
   const kProxyHandlerOrTargetRevoked: constexpr MessageTemplate
   generates 'MessageTemplate::kProxyHandlerOrTargetRevoked';
   const kProxyRevoked: constexpr MessageTemplate
   generates 'MessageTemplate::kProxyRevoked';
+  const kProxyTrapReturnedFalsishFor: constexpr MessageTemplate
+  generates 'MessageTemplate::kProxyTrapReturnedFalsishFor';
+  const kProxyPrivate: constexpr MessageTemplate
+  generates 'MessageTemplate::kProxyPrivate';
 
   const kProxyGet: constexpr int31
   generates 'JSProxy::AccessKind::kGet';
diff --git a/test/mjsunit/es6/regress/regress-9234.js b/test/mjsunit/es6/regress/regress-9234.js
new file mode 100644
index 0000000..e0c8b05
--- /dev/null
+++ b/test/mjsunit/es6/regress/regress-9234.js
@@ -0,0 +1,35 @@
+// 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.
+
+// Flags: --allow-natives-syntax
+
+(function returnFalsishStrict() {
+  "use strict";
+
+  function trySet(o) {
+    o["bla"] = 0;
+  }
+
+  var proxy = new Proxy({}, {});
+  var proxy2 = new Proxy({}, { set() { return ""; } });
+
+  trySet(proxy);
+  trySet(proxy);
+  assertThrows(() => trySet(proxy2), TypeError);
+})();
+
+(function privateSymbolStrict() {
+  "use strict";
+  var proxy = new Proxy({}, {});
+  var proxy2 = new Proxy({a: 1}, { set() { return true; } });
+
+  function trySet(o) {
+    var symbol = o == proxy2 ? %CreatePrivateSymbol("private"): 1;
+    o[symbol] = 0;
+  }
+
+  trySet(proxy);
+  trySet(proxy);
+  assertThrows(() => trySet(proxy2), TypeError);
+})();