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

Add GetPropertyWithReceiver stub for proxy get trap

GetPropertyWithReceiver is similar to GetProperty, except that additional receiver parameter is used in TryPrototypeChainLookup to support GetPropertyWithReceiver stub.
We only use this stub in ProxyGetProperty builtin for now.

Bug: v8:8958
Change-Id: Ied60e4f6ee6e09bca2f161048b481a0bf37a78a7
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1676879
Commit-Queue: Z Nguyen-Huu <duongn@microsoft.com>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62431}
parent 327190f4
......@@ -1142,6 +1142,7 @@ namespace internal {
ASM(StackCheck, Dummy) \
ASM(DoubleToI, Dummy) \
TFC(GetProperty, GetProperty) \
TFS(GetPropertyWithReceiver, kObject, kKey, kReceiver, kOnNonExistent) \
TFS(SetProperty, kReceiver, kKey, kValue) \
TFS(SetPropertyInLiteral, kReceiver, kKey, kValue) \
ASM(MemCopyUint8Uint8, CCall) \
......
......@@ -908,6 +908,8 @@ TF_BUILTIN(GetProperty, CodeStubAssembler) {
Node* object = Parameter(Descriptor::kObject);
Node* key = Parameter(Descriptor::kKey);
Node* context = Parameter(Descriptor::kContext);
// TODO(duongn): consider tailcalling to GetPropertyWithReceiver(object,
// object, key, OnNonExistent::kReturnUndefined).
Label if_notfound(this), if_proxy(this, Label::kDeferred),
if_slow(this, Label::kDeferred);
......@@ -933,7 +935,7 @@ TF_BUILTIN(GetProperty, CodeStubAssembler) {
Goto(if_bailout);
};
TryPrototypeChainLookup(object, key, lookup_property_in_holder,
TryPrototypeChainLookup(object, object, key, lookup_property_in_holder,
lookup_element_in_holder, &if_notfound, &if_slow,
&if_proxy);
......@@ -956,6 +958,71 @@ TF_BUILTIN(GetProperty, CodeStubAssembler) {
}
}
// ES6 [[Get]] operation with Receiver.
TF_BUILTIN(GetPropertyWithReceiver, CodeStubAssembler) {
Node* object = Parameter(Descriptor::kObject);
Node* key = Parameter(Descriptor::kKey);
Node* context = Parameter(Descriptor::kContext);
Node* receiver = Parameter(Descriptor::kReceiver);
Node* on_non_existent = Parameter(Descriptor::kOnNonExistent);
Label if_notfound(this), if_proxy(this, Label::kDeferred),
if_slow(this, Label::kDeferred);
CodeStubAssembler::LookupInHolder lookup_property_in_holder =
[=](Node* receiver, Node* holder, Node* holder_map,
Node* holder_instance_type, Node* unique_name, Label* next_holder,
Label* if_bailout) {
VARIABLE(var_value, MachineRepresentation::kTagged);
Label if_found(this);
TryGetOwnProperty(context, receiver, holder, holder_map,
holder_instance_type, unique_name, &if_found,
&var_value, next_holder, if_bailout);
BIND(&if_found);
Return(var_value.value());
};
CodeStubAssembler::LookupInHolder lookup_element_in_holder =
[=](Node* receiver, Node* holder, Node* holder_map,
Node* holder_instance_type, Node* index, Label* next_holder,
Label* if_bailout) {
// Not supported yet.
Use(next_holder);
Goto(if_bailout);
};
TryPrototypeChainLookup(receiver, object, key, lookup_property_in_holder,
lookup_element_in_holder, &if_notfound, &if_slow,
&if_proxy);
BIND(&if_notfound);
Label throw_reference_error(this);
GotoIf(WordEqual(on_non_existent,
SmiConstant(OnNonExistent::kThrowReferenceError)),
&throw_reference_error);
CSA_ASSERT(this, WordEqual(on_non_existent,
SmiConstant(OnNonExistent::kReturnUndefined)));
Return(UndefinedConstant());
BIND(&throw_reference_error);
Return(CallRuntime(Runtime::kThrowReferenceError, context, key));
BIND(&if_slow);
TailCallRuntime(Runtime::kGetPropertyWithReceiver, context, object, key,
receiver, on_non_existent);
BIND(&if_proxy);
{
// Convert the {key} to a Name first.
Node* name = CallBuiltin(Builtins::kToName, context, key);
// The {object} is a JSProxy instance, look up the {name} on it, passing
// {object} both as receiver and holder. If {name} is absent we can safely
// return undefined from here.
TailCallBuiltin(Builtins::kProxyGetProperty, context, object, name,
receiver, on_non_existent);
}
}
// ES6 [[Set]] operation.
TF_BUILTIN(SetProperty, CodeStubAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
......
......@@ -6,9 +6,8 @@
namespace proxy {
extern transitioning runtime
GetPropertyWithReceiver(implicit context: Context)(Object, Name, Object, Smi):
Object;
extern transitioning builtin GetPropertyWithReceiver(
implicit context: Context)(Object, Name, Object, Smi): 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
......@@ -40,7 +39,6 @@ namespace proxy {
// 6. Let trap be ? GetMethod(handler, "get").
// 7. If trap is undefined, then (see 7.a below).
// 7.a. Return ? target.[[Get]](P, Receiver).
// TODO(mslekova): Introduce GetPropertyWithReceiver stub
const trap: Callable = GetMethod(handler, 'get')
otherwise return GetPropertyWithReceiver(
target, name, receiverValue, onNonExistent);
......
......@@ -9856,15 +9856,16 @@ void CodeStubAssembler::BranchIfMaybeSpecialIndex(TNode<String> name_string,
}
void CodeStubAssembler::TryPrototypeChainLookup(
Node* receiver, Node* key, const LookupInHolder& lookup_property_in_holder,
Node* receiver, Node* object, Node* key,
const LookupInHolder& lookup_property_in_holder,
const LookupInHolder& lookup_element_in_holder, Label* if_end,
Label* if_bailout, Label* if_proxy) {
// Ensure receiver is JSReceiver, otherwise bailout.
Label if_objectisnotsmi(this);
Branch(TaggedIsSmi(receiver), if_bailout, &if_objectisnotsmi);
Branch(TaggedIsSmi(object), if_bailout, &if_objectisnotsmi);
BIND(&if_objectisnotsmi);
Node* map = LoadMap(receiver);
Node* map = LoadMap(object);
Node* instance_type = LoadMapInstanceType(map);
{
Label if_objectisreceiver(this);
......@@ -9874,9 +9875,7 @@ void CodeStubAssembler::TryPrototypeChainLookup(
if_bailout);
BIND(&if_objectisreceiver);
if (if_proxy) {
GotoIf(InstanceTypeEqual(instance_type, JS_PROXY_TYPE), if_proxy);
}
GotoIf(InstanceTypeEqual(instance_type, JS_PROXY_TYPE), if_proxy);
}
VARIABLE(var_index, MachineType::PointerRepresentation());
......@@ -9888,7 +9887,7 @@ void CodeStubAssembler::TryPrototypeChainLookup(
BIND(&if_iskeyunique);
{
VARIABLE(var_holder, MachineRepresentation::kTagged, receiver);
VARIABLE(var_holder, MachineRepresentation::kTagged, object);
VARIABLE(var_holder_map, MachineRepresentation::kTagged, map);
VARIABLE(var_holder_instance_type, MachineRepresentation::kWord32,
instance_type);
......@@ -9934,7 +9933,7 @@ void CodeStubAssembler::TryPrototypeChainLookup(
}
BIND(&if_keyisindex);
{
VARIABLE(var_holder, MachineRepresentation::kTagged, receiver);
VARIABLE(var_holder, MachineRepresentation::kTagged, object);
VARIABLE(var_holder_map, MachineRepresentation::kTagged, map);
VARIABLE(var_holder_instance_type, MachineRepresentation::kWord32,
instance_type);
......@@ -12706,7 +12705,7 @@ TNode<Oddball> CodeStubAssembler::HasProperty(SloppyTNode<Context> context,
&return_true, &return_false, next_holder, if_bailout);
};
TryPrototypeChainLookup(object, key, lookup_property_in_holder,
TryPrototypeChainLookup(object, object, key, lookup_property_in_holder,
lookup_element_in_holder, &return_false,
&call_runtime, &if_proxy);
......
......@@ -2999,11 +2999,11 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
// If it can't handle the case {receiver}/{key} case then the control goes
// to {if_bailout}.
// If {if_proxy} is nullptr, proxies go to if_bailout.
void TryPrototypeChainLookup(Node* receiver, Node* key,
void TryPrototypeChainLookup(Node* receiver, Node* object, Node* key,
const LookupInHolder& lookup_property_in_holder,
const LookupInHolder& lookup_element_in_holder,
Label* if_end, Label* if_bailout,
Label* if_proxy = nullptr);
Label* if_proxy);
// Instanceof helpers.
// Returns true if {object} has {prototype} somewhere in it's prototype
......
......@@ -548,6 +548,8 @@ void AccessorAssembler::HandleLoadICSmiHandlerLoadNamedCase(
Goto(&to_name_failed);
BIND(&to_name_failed);
// TODO(duongn): use GetPropertyWithReceiver builtin once
// |lookup_element_in_holder| supports elements.
exit_point->ReturnCallRuntime(Runtime::kGetPropertyWithReceiver,
p->context, holder, p->name, p->receiver,
SmiConstant(on_nonexistent));
......
......@@ -17,5 +17,5 @@ for (let val of values) {
var proto = Object.getPrototypeOf(val);
var proxy = new Proxy({}, {});
Object.setPrototypeOf(proto, proxy);
Object.setPrototypeOf(proxy, proto);
}
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