diff --git a/BUILD.gn b/BUILD.gn index b27fbf3325..f0a0d21b41 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1005,6 +1005,8 @@ v8_source_set("v8_builtins_generators") { "src/builtins/builtins-promise-gen.h", "src/builtins/builtins-proxy-gen.cc", "src/builtins/builtins-proxy-gen.h", + "src/builtins/builtins-proxy-helpers-gen.cc", + "src/builtins/builtins-proxy-helpers-gen.h", "src/builtins/builtins-regexp-gen.cc", "src/builtins/builtins-regexp-gen.h", "src/builtins/builtins-sharedarraybuffer-gen.cc", diff --git a/src/builtins/builtins-definitions.h b/src/builtins/builtins-definitions.h index b239ddaba3..e7b41ed23e 100644 --- a/src/builtins/builtins-definitions.h +++ b/src/builtins/builtins-definitions.h @@ -779,7 +779,6 @@ namespace internal { SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ TFS(ProxyGetProperty, kProxy, kName, kReceiverValue) \ TFS(ProxyHasProperty, kProxy, kName) \ - TFS(ProxySetProperty, kProxy, kName, kValue, kReceiverValue, kLanguageMode) \ \ /* Reflect */ \ ASM(ReflectApply) \ diff --git a/src/builtins/builtins-proxy-gen.cc b/src/builtins/builtins-proxy-gen.cc index 1d2b5c9ca3..745c2cce3e 100644 --- a/src/builtins/builtins-proxy-gen.cc +++ b/src/builtins/builtins-proxy-gen.cc @@ -322,257 +322,6 @@ TF_BUILTIN(ProxyHasProperty, ProxiesCodeStubAssembler) { StringConstant("has"), proxy); } -TF_BUILTIN(ProxyGetProperty, ProxiesCodeStubAssembler) { - Node* context = Parameter(Descriptor::kContext); - Node* proxy = Parameter(Descriptor::kProxy); - Node* name = Parameter(Descriptor::kName); - 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)); - CSA_ASSERT(this, Word32Equal(IsPrivateSymbol(name), Int32Constant(0))); - - Label throw_proxy_handler_revoked(this, Label::kDeferred), - trap_undefined(this); - - // 2. Let handler be O.[[ProxyHandler]]. - Node* handler = LoadObjectField(proxy, JSProxy::kHandlerOffset); - - // 3. If handler is null, throw a TypeError exception. - GotoIf(IsNull(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, "get"). - // 7. If trap is undefined, then (see 7.a below). - Handle trap_name = factory()->get_string(); - Node* trap = GetMethod(context, handler, trap_name, &trap_undefined); - - // 8. Let trapResult be ? Call(trap, handler, « target, P, Receiver »). - Node* trap_result = CallJS( - CodeFactory::Call(isolate(), ConvertReceiverMode::kNotNullOrUndefined), - context, trap, handler, target, name, receiver); - - // 9. Let targetDesc be ? target.[[GetOwnProperty]](P). - Label return_result(this); - CheckGetSetTrapResult(context, target, proxy, name, trap_result, - &return_result, JSProxy::kGet); - - BIND(&return_result); - { - // 11. Return trapResult. - Return(trap_result); - } - - BIND(&trap_undefined); - { - // 7.a. Return ? target.[[Get]](P, Receiver). - // TODO(mslekova): Introduce GetPropertyWithReceiver stub - Return(CallRuntime(Runtime::kGetPropertyWithReceiver, context, target, name, - receiver)); - } - - BIND(&throw_proxy_handler_revoked); - ThrowTypeError(context, MessageTemplate::kProxyRevoked, "get"); -} - -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); - Node* language_mode = Parameter(Descriptor::kLanguageMode); - - 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 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); - CheckGetSetTrapResult(context, target, proxy, name, value, &success, - JSProxy::kSet); - } - - BIND(&failure); - { - Label if_throw(this, Label::kDeferred); - Branch(SmiEqual(language_mode, SmiConstant(STRICT)), &if_throw, &success); - - BIND(&if_throw); - ThrowTypeError(context, MessageTemplate::kProxyTrapReturnedFalsishFor, - HeapConstant(set_string), name); - } - - // 12. Return true. - BIND(&success); - Return(value); - - BIND(&private_symbol); - { - Label failure(this), throw_error(this, Label::kDeferred); - - Branch(SmiEqual(language_mode, SmiConstant(STRICT)), &throw_error, - &failure); - - BIND(&failure); - Return(UndefinedConstant()); - - BIND(&throw_error); - ThrowTypeError(context, MessageTemplate::kProxyPrivate); - } - - BIND(&trap_undefined); - { - // 7.a. Return ? target.[[Set]](P, V, Receiver). - CallRuntime(Runtime::kSetPropertyWithReceiver, context, target, name, value, - receiver, language_mode); - Return(value); - } - - BIND(&throw_proxy_handler_revoked); - ThrowTypeError(context, MessageTemplate::kProxyRevoked, "set"); -} - -void ProxiesCodeStubAssembler::CheckGetSetTrapResult( - Node* context, Node* target, Node* proxy, Node* name, Node* trap_result, - Label* check_passed, JSProxy::AccessKind access_kind) { - Node* map = LoadMap(target); - VARIABLE(var_value, MachineRepresentation::kTagged); - VARIABLE(var_details, MachineRepresentation::kWord32); - VARIABLE(var_raw_value, MachineRepresentation::kTagged); - - Label if_found_value(this), check_in_runtime(this, Label::kDeferred); - - Node* instance_type = LoadInstanceType(target); - TryGetOwnProperty(context, target, target, map, instance_type, name, - &if_found_value, &var_value, &var_details, &var_raw_value, - check_passed, &check_in_runtime); - - BIND(&if_found_value); - { - Label throw_non_configurable_data(this, Label::kDeferred), - throw_non_configurable_accessor(this, Label::kDeferred), - check_accessor(this), check_data(this); - - // If targetDesc is not undefined and targetDesc.[[Configurable]] is - // false, then: - GotoIfNot(IsSetWord32(var_details.value(), - PropertyDetails::kAttributesDontDeleteMask), - check_passed); - - // If IsDataDescriptor(targetDesc) is true and - // targetDesc.[[Writable]] is false, then: - BranchIfAccessorPair(var_raw_value.value(), &check_accessor, &check_data); - - BIND(&check_data); - { - Node* read_only = IsSetWord32(var_details.value(), - PropertyDetails::kAttributesReadOnlyMask); - GotoIfNot(read_only, check_passed); - - // If SameValue(trapResult, targetDesc.[[Value]]) is false, - // throw a TypeError exception. - GotoIfNot(SameValue(trap_result, var_value.value()), - &throw_non_configurable_data); - Goto(check_passed); - } - - BIND(&check_accessor); - { - Node* accessor_pair = var_raw_value.value(); - - if (access_kind == JSProxy::kGet) { - Label continue_check(this, Label::kDeferred); - // 10.b. If IsAccessorDescriptor(targetDesc) is true and - // targetDesc.[[Get]] is undefined, then: - Node* getter = - LoadObjectField(accessor_pair, AccessorPair::kGetterOffset); - // Here we check for null as well because if the getter was never - // defined it's set as null. - GotoIf(IsUndefined(getter), &continue_check); - GotoIf(IsNull(getter), &continue_check); - Goto(check_passed); - - // 10.b.i. If trapResult is not undefined, throw a TypeError exception. - BIND(&continue_check); - GotoIfNot(IsUndefined(trap_result), &throw_non_configurable_accessor); - } else { - // 11.b.i. If targetDesc.[[Set]] is undefined, throw a TypeError - // exception. - Node* setter = - LoadObjectField(accessor_pair, AccessorPair::kSetterOffset); - GotoIf(IsUndefined(setter), &throw_non_configurable_accessor); - GotoIf(IsNull(setter), &throw_non_configurable_accessor); - } - Goto(check_passed); - } - - BIND(&check_in_runtime); - { - CallRuntime(Runtime::kCheckProxyGetSetTrapResult, context, name, target, - trap_result, SmiConstant(access_kind)); - Return(trap_result); - } - - BIND(&throw_non_configurable_data); - { - ThrowTypeError(context, MessageTemplate::kProxyGetNonConfigurableData, - name, var_value.value(), trap_result); - } - - BIND(&throw_non_configurable_accessor); - { - ThrowTypeError(context, MessageTemplate::kProxyGetNonConfigurableAccessor, - name, trap_result); - } - } -} - void ProxiesCodeStubAssembler::CheckHasTrapResult(Node* context, Node* target, Node* proxy, Node* name, Label* check_passed, diff --git a/src/builtins/builtins-proxy-gen.h b/src/builtins/builtins-proxy-gen.h index 67203ee4d9..34ef73debf 100644 --- a/src/builtins/builtins-proxy-gen.h +++ b/src/builtins/builtins-proxy-gen.h @@ -16,22 +16,6 @@ class ProxiesCodeStubAssembler : public CodeStubAssembler { explicit ProxiesCodeStubAssembler(compiler::CodeAssemblerState* state) : CodeStubAssembler(state) {} - void BranchIfAccessorPair(Node* value, Label* if_accessor_pair, - Label* if_not_accessor_pair) { - GotoIf(TaggedIsSmi(value), if_not_accessor_pair); - Branch(IsAccessorPair(value), if_accessor_pair, if_not_accessor_pair); - } - - // 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); - protected: void GotoIfRevokedProxy(Node* object, Label* if_proxy_revoked); Node* AllocateProxy(Node* target, Node* handler, Node* context); @@ -40,10 +24,6 @@ class ProxiesCodeStubAssembler : public CodeStubAssembler { ParameterMode mode); void CheckHasTrapResult(Node* context, Node* target, Node* proxy, Node* name, Label* check_passed, Label* if_bailout); - - void CheckGetSetTrapResult(Node* context, Node* target, Node* proxy, - Node* name, Node* trap_result, Label* if_not_found, - JSProxy::AccessKind access_kind); }; } // namespace internal diff --git a/src/builtins/builtins-proxy-helpers-gen.cc b/src/builtins/builtins-proxy-helpers-gen.cc new file mode 100644 index 0000000000..ca2e9bb6d7 --- /dev/null +++ b/src/builtins/builtins-proxy-helpers-gen.cc @@ -0,0 +1,160 @@ +// Copyright 2017 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-helpers-gen.h" +#include "src/builtins/builtins-utils-gen.h" + +namespace v8 { +namespace internal { +TF_BUILTIN(ProxyGetProperty, ProxyAssembler) { + Node* context = Parameter(Descriptor::kContext); + Node* proxy = Parameter(Descriptor::kProxy); + Node* name = Parameter(Descriptor::kName); + Node* receiver = Parameter(Descriptor::kReceiverValue); + + CSA_ASSERT(this, IsJSProxy(proxy)); + + // 1. Assert: IsPropertyKey(P) is true. + CSA_ASSERT(this, IsName(name)); + + Label throw_proxy_handler_revoked(this, Label::kDeferred), + trap_undefined(this), no_target_desc(this, Label::kDeferred), + trap_not_callable(this, Label::kDeferred); + + // 2. Let handler be O.[[ProxyHandler]]. + Node* handler = LoadObjectField(proxy, JSProxy::kHandlerOffset); + + // 3. If handler is null, throw a TypeError exception. + GotoIf(IsNull(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, "get"). + // 7. If trap is undefined, then (see 7.a below). + Handle trap_name = factory()->get_string(); + Node* trap = GetMethod(context, handler, trap_name, &trap_undefined); + + GotoIf(TaggedIsSmi(trap), &trap_not_callable); + GotoIfNot(IsCallable(trap), &trap_not_callable); + + // 8. Let trapResult be ? Call(trap, handler, « target, P, Receiver »). + Node* trap_result = CallJS(CodeFactory::Call(isolate()), context, trap, + handler, target, name, receiver); + // 9. Let targetDesc be ? target.[[GetOwnProperty]](P). + Label return_result(this); + CheckGetTrapResult(context, target, proxy, name, trap_result, &return_result, + &no_target_desc); + + BIND(&return_result); + { + // 11. Return trapResult. + Return(trap_result); + } + + BIND(&no_target_desc); + { + CSA_ASSERT(this, IsJSReceiver(target)); + CallRuntime(Runtime::kCheckProxyGetTrapResult, context, name, target, + trap_result); + Return(trap_result); + } + + BIND(&trap_undefined); + { + // 7.a. Return ? target.[[Get]](P, Receiver). + Return(CallRuntime(Runtime::kGetPropertyWithReceiver, context, target, name, + receiver)); + } + + BIND(&throw_proxy_handler_revoked); + { ThrowTypeError(context, MessageTemplate::kProxyRevoked, "get"); } + + BIND(&trap_not_callable); + { + ThrowTypeError(context, MessageTemplate::kPropertyNotFunction, trap, + StringConstant("get"), receiver); + } +} + +void ProxyAssembler::CheckGetTrapResult(Node* context, Node* target, + Node* proxy, Node* name, + Node* trap_result, Label* check_passed, + Label* if_bailout) { + Node* map = LoadMap(target); + VARIABLE(var_value, MachineRepresentation::kTagged); + VARIABLE(var_details, MachineRepresentation::kWord32); + VARIABLE(var_raw_value, MachineRepresentation::kTagged); + + Label if_found_value(this, Label::kDeferred); + + Node* instance_type = LoadInstanceType(target); + TryGetOwnProperty(context, proxy, target, map, instance_type, name, + &if_found_value, &var_value, &var_details, &var_raw_value, + check_passed, if_bailout); + + BIND(&if_found_value); + { + Label throw_non_configurable_data(this, Label::kDeferred), + throw_non_configurable_accessor(this, Label::kDeferred), + check_accessor(this), check_data(this); + + // 10. If targetDesc is not undefined and targetDesc.[[Configurable]] is + // false, then: + GotoIfNot(IsSetWord32(var_details.value(), + PropertyDetails::kAttributesDontDeleteMask), + check_passed); + + // 10.a. If IsDataDescriptor(targetDesc) is true and + // targetDesc.[[Writable]] is false, then: + BranchIfAccessorPair(var_raw_value.value(), &check_accessor, &check_data); + + BIND(&check_data); + { + Node* read_only = IsSetWord32(var_details.value(), + PropertyDetails::kAttributesReadOnlyMask); + GotoIfNot(read_only, check_passed); + + // 10.a.i. If SameValue(trapResult, targetDesc.[[Value]]) is false, + // throw a TypeError exception. + GotoIfNot(SameValue(trap_result, var_value.value()), + &throw_non_configurable_data); + Goto(check_passed); + } + + BIND(&check_accessor); + { + // 10.b. If IsAccessorDescriptor(targetDesc) is true and + // targetDesc.[[Get]] is undefined, then: + Node* accessor_pair = var_raw_value.value(); + Node* getter = + LoadObjectField(accessor_pair, AccessorPair::kGetterOffset); + + // Here we check for null as well because if the getter was never + // defined it's set as null. + GotoIfNot(Word32Or(IsUndefined(getter), IsNull(getter)), check_passed); + + // 10.b.i. If trapResult is not undefined, throw a TypeError exception. + GotoIfNot(IsUndefined(trap_result), &throw_non_configurable_accessor); + Goto(check_passed); + } + + BIND(&throw_non_configurable_data); + { + ThrowTypeError(context, MessageTemplate::kProxyGetNonConfigurableData, + name, var_value.value(), trap_result); + } + + BIND(&throw_non_configurable_accessor); + { + ThrowTypeError(context, MessageTemplate::kProxyGetNonConfigurableAccessor, + name, trap_result); + } + } +} +} // namespace internal +} // namespace v8 diff --git a/src/builtins/builtins-proxy-helpers-gen.h b/src/builtins/builtins-proxy-helpers-gen.h new file mode 100644 index 0000000000..a72abbdd4a --- /dev/null +++ b/src/builtins/builtins-proxy-helpers-gen.h @@ -0,0 +1,38 @@ +// Copyright 2017 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. + +#ifndef V8_BUILTINS_BUILTINS_PROXY_HELPERS_GEN_H_ +#define V8_BUILTINS_BUILTINS_PROXY_HELPERS_GEN_H_ + +#include "src/code-stub-assembler.h" + +namespace v8 { +namespace internal { +using compiler::Node; + +class ProxyAssembler : public CodeStubAssembler { + public: + explicit ProxyAssembler(compiler::CodeAssemblerState* state) + : CodeStubAssembler(state) {} + + void BranchIfAccessorPair(Node* value, Label* if_accessor_pair, + Label* if_not_accessor_pair) { + GotoIf(TaggedIsSmi(value), if_not_accessor_pair); + Branch(IsAccessorPair(value), if_accessor_pair, if_not_accessor_pair); + } + + // ES6 section 9.5.8 [[Get]] ( P, Receiver ) + Node* ProxyGetProperty(Node* context, Node* proxy, Node* name, + Node* receiver); + + protected: + void CheckGetTrapResult(Node* context, Node* target, Node* proxy, Node* name, + Node* trap_result, Label* if_not_found, + Label* if_bailout); +}; + +} // namespace internal +} // namespace v8 + +#endif // V8_BUILTINS_BUILTINS_PROXY_HELPERS_GEN_H_ diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc index 542480943e..57b6942032 100644 --- a/src/code-stub-assembler.cc +++ b/src/code-stub-assembler.cc @@ -6916,7 +6916,6 @@ void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value, ElementsKind elements_kind, KeyedAccessStoreMode store_mode, Label* bailout) { - CSA_ASSERT(this, Word32BinaryNot(IsJSProxy(object))); Node* elements = LoadElements(object); if (IsSmiOrObjectElementsKind(elements_kind) && store_mode != STORE_NO_TRANSITION_HANDLE_COW) { diff --git a/src/feedback-vector.cc b/src/feedback-vector.cc index 65d2e56c89..96ef583512 100644 --- a/src/feedback-vector.cc +++ b/src/feedback-vector.cc @@ -852,10 +852,6 @@ KeyedAccessStoreMode KeyedStoreICNexus::GetKeyedAccessStoreMode() const { // Element store with prototype chain check. Handle data_handler = Handle::cast(maybe_code_handler); handler = handle(Code::cast(data_handler->value2())); - } else if (maybe_code_handler->IsSmi()) { - // Skip proxy handlers. - DCHECK_EQ(*maybe_code_handler, *StoreHandler::StoreProxy(GetIsolate())); - continue; } else { // Element store without prototype chain check. handler = Handle::cast(maybe_code_handler); diff --git a/src/ic/accessor-assembler.cc b/src/ic/accessor-assembler.cc index 76236e174c..1dee130336 100644 --- a/src/ic/accessor-assembler.cc +++ b/src/ic/accessor-assembler.cc @@ -261,8 +261,8 @@ void AccessorAssembler::HandleLoadICSmiHandlerCase( Label constant(this), field(this), normal(this, Label::kDeferred), interceptor(this, Label::kDeferred), nonexistent(this), - accessor(this, Label::kDeferred), global(this, Label::kDeferred), - module_export(this, Label::kDeferred), proxy(this, Label::kDeferred); + accessor(this, Label::kDeferred), proxy(this, Label::kDeferred), + global(this, Label::kDeferred), module_export(this, Label::kDeferred); GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kField)), &field); GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kConstant)), @@ -370,35 +370,9 @@ void AccessorAssembler::HandleLoadICSmiHandlerCase( BIND(&proxy); { - VARIABLE(var_index, MachineType::PointerRepresentation()); - VARIABLE(var_unique, MachineRepresentation::kTagged); - - Label if_index(this), if_unique_name(this), - to_name_failed(this, Label::kDeferred); - - if (support_elements == kSupportElements) { - TryToName(p->name, &if_index, &var_index, &if_unique_name, &var_unique, - &to_name_failed); - - BIND(&if_unique_name); - exit_point->ReturnCallStub( - Builtins::CallableFor(isolate(), Builtins::kProxyGetProperty), - p->context, holder, var_unique.value(), p->receiver); - - BIND(&if_index); - // TODO(mslekova): introduce TryToName that doesn't try to compute - // the intptr index value - Goto(&to_name_failed); - - BIND(&to_name_failed); - exit_point->ReturnCallRuntime(Runtime::kGetPropertyWithReceiver, - p->context, holder, p->name, p->receiver); - - } else { - exit_point->ReturnCallStub( - Builtins::CallableFor(isolate(), Builtins::kProxyGetProperty), - p->context, holder, p->name, p->receiver); - } + exit_point->ReturnCallStub( + Builtins::CallableFor(isolate(), Builtins::kProxyGetProperty), + p->context, holder, p->name, p->receiver); } BIND(&global); @@ -638,7 +612,7 @@ void AccessorAssembler::JumpIfDataProperty(Node* details, Label* writable, void AccessorAssembler::HandleStoreICHandlerCase( const StoreICParameters* p, Node* handler, Label* miss, - LanguageMode language_mode, ElementSupport support_elements) { + ElementSupport support_elements) { Label if_smi_handler(this), if_nonsmi_handler(this); Label if_proto_handler(this), if_element_handler(this), call_handler(this), store_global(this); @@ -652,17 +626,10 @@ void AccessorAssembler::HandleStoreICHandlerCase( Node* holder = p->receiver; Node* handler_word = SmiUntag(handler); - Label if_fast_smi(this), if_proxy(this); - - STATIC_ASSERT(StoreHandler::kStoreNormal + 1 == StoreHandler::kProxy); - STATIC_ASSERT(StoreHandler::kProxy + 1 == StoreHandler::kKindsNumber); - - Node* handler_kind = DecodeWord(handler_word); - GotoIf(IntPtrLessThan(handler_kind, - IntPtrConstant(StoreHandler::kStoreNormal)), - &if_fast_smi); - GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kProxy)), - &if_proxy); + Label if_fast_smi(this), slow(this); + GotoIfNot( + WordEqual(handler_word, IntPtrConstant(StoreHandler::kStoreNormal)), + &if_fast_smi); Node* properties = LoadSlowProperties(holder); @@ -688,9 +655,6 @@ void AccessorAssembler::HandleStoreICHandlerCase( BIND(&if_fast_smi); // Handle non-transitioning field stores. HandleStoreICSmiHandlerCase(handler_word, holder, p->value, nullptr, miss); - - BIND(&if_proxy); - HandleStoreToProxy(p, holder, miss, support_elements, language_mode); } BIND(&if_nonsmi_handler); @@ -709,10 +673,7 @@ void AccessorAssembler::HandleStoreICHandlerCase( } BIND(&if_proto_handler); - { - HandleStoreICProtoHandler(p, handler, miss, support_elements, - language_mode); - } + { HandleStoreICProtoHandler(p, handler, miss, support_elements); } // |handler| is a heap object. Must be code, call it. BIND(&call_handler); @@ -801,7 +762,7 @@ void AccessorAssembler::HandleStoreICElementHandlerCase( void AccessorAssembler::HandleStoreICProtoHandler( const StoreICParameters* p, Node* handler, Label* miss, - ElementSupport support_elements, LanguageMode language_mode) { + ElementSupport support_elements) { // IC dispatchers rely on these assumptions to be held. STATIC_ASSERT(FixedArray::kLengthOffset == StoreHandler::kTransitionCellOffset); @@ -831,12 +792,12 @@ void AccessorAssembler::HandleStoreICProtoHandler( VARIABLE(var_transition, MachineRepresentation::kTagged); Label if_transition(this), if_transition_to_constant(this), - if_store_normal(this), if_proxy(this), do_store(this); + if_store_normal(this); BIND(&tuple_handler); { Node* transition = LoadWeakCellValue(maybe_transition_cell, miss); var_transition.Bind(transition); - Goto(&do_store); + Goto(&if_transition); } BIND(&array_handler); @@ -854,19 +815,7 @@ void AccessorAssembler::HandleStoreICProtoHandler( LoadFixedArrayElement(handler, StoreHandler::kTransitionCellIndex); Node* transition = LoadWeakCellValue(maybe_transition_cell, miss); var_transition.Bind(transition); - Goto(&do_store); - } - - BIND(&do_store); - { - Branch(SmiEqual(smi_or_code, SmiConstant(StoreHandler::kProxy)), &if_proxy, - &if_transition); - } - - BIND(&if_proxy); - { - Node* proxy = var_transition.value(); - HandleStoreToProxy(p, proxy, miss, support_elements, language_mode); + Goto(&if_transition); } BIND(&if_transition); @@ -917,8 +866,9 @@ void AccessorAssembler::HandleStoreICProtoHandler( DescriptorArray::kEntryValueIndex)); Node* descriptors = LoadMapDescriptors(transition); CSA_ASSERT( - this, UintPtrLessThan(descriptor, - LoadAndUntagFixedArrayBaseLength(descriptors))); + this, + UintPtrLessThan(descriptor, + LoadAndUntagFixedArrayBaseLength(descriptors))); Node* constant = LoadFixedArrayElement(descriptors, value_index); GotoIf(WordNotEqual(p->value, constant), miss); @@ -965,42 +915,6 @@ void AccessorAssembler::HandleStoreICProtoHandler( } } -void AccessorAssembler::HandleStoreToProxy(const StoreICParameters* p, - Node* proxy, Label* miss, - ElementSupport support_elements, - LanguageMode language_mode) { - VARIABLE(var_index, MachineType::PointerRepresentation()); - VARIABLE(var_unique, MachineRepresentation::kTagged); - - Label if_index(this), if_unique_name(this), - to_name_failed(this, Label::kDeferred); - - if (support_elements == kSupportElements) { - TryToName(p->name, &if_index, &var_index, &if_unique_name, &var_unique, - &to_name_failed); - - BIND(&if_unique_name); - CallBuiltin(Builtins::kProxySetProperty, p->context, proxy, - var_unique.value(), p->value, p->receiver, - SmiConstant(language_mode)); - Return(p->value); - - // The index case is handled earlier by the runtime. - BIND(&if_index); - // TODO(mslekova): introduce TryToName that doesn't try to compute - // the intptr index value - Goto(&to_name_failed); - - BIND(&to_name_failed); - TailCallRuntime(Runtime::kSetPropertyWithReceiver, p->context, proxy, - p->name, p->value, p->receiver, SmiConstant(language_mode)); - } else { - Node* name = ToName(p->context, p->name); - TailCallBuiltin(Builtins::kProxySetProperty, p->context, proxy, name, - p->value, p->receiver, SmiConstant(language_mode)); - } -} - void AccessorAssembler::HandleStoreICSmiHandlerCase(Node* handler_word, Node* holder, Node* value, Node* transition, @@ -2323,7 +2237,7 @@ void AccessorAssembler::StoreIC(const StoreICParameters* p, BIND(&if_handler); { Comment("StoreIC_if_handler"); - HandleStoreICHandlerCase(p, var_handler.value(), &miss, language_mode); + HandleStoreICHandlerCase(p, var_handler.value(), &miss); } BIND(&try_polymorphic); @@ -2384,8 +2298,7 @@ void AccessorAssembler::KeyedStoreIC(const StoreICParameters* p, BIND(&if_handler); { Comment("KeyedStoreIC_if_handler"); - HandleStoreICHandlerCase(p, var_handler.value(), &miss, language_mode, - kSupportElements); + HandleStoreICHandlerCase(p, var_handler.value(), &miss, kSupportElements); } BIND(&try_polymorphic); diff --git a/src/ic/accessor-assembler.h b/src/ic/accessor-assembler.h index cd3d8d449d..c771b2ff5a 100644 --- a/src/ic/accessor-assembler.h +++ b/src/ic/accessor-assembler.h @@ -93,7 +93,6 @@ class AccessorAssembler : public CodeStubAssembler { enum ElementSupport { kOnlyProperties, kSupportElements }; void HandleStoreICHandlerCase( const StoreICParameters* p, Node* handler, Label* miss, - LanguageMode language_mode, ElementSupport support_elements = kOnlyProperties); void JumpIfDataProperty(Node* details, Label* writable, Label* readonly); @@ -165,8 +164,7 @@ class AccessorAssembler : public CodeStubAssembler { Node* handler, Label* miss); void HandleStoreICProtoHandler(const StoreICParameters* p, Node* handler, - Label* miss, ElementSupport support_elements, - LanguageMode language_mode); + Label* miss, ElementSupport support_elements); // If |transition| is nullptr then the normal field store is generated or // transitioning store otherwise. void HandleStoreICSmiHandlerCase(Node* handler_word, Node* holder, @@ -177,10 +175,6 @@ class AccessorAssembler : public CodeStubAssembler { Representation representation, Node* value, Node* transition, Label* miss); - void HandleStoreToProxy(const StoreICParameters* p, Node* proxy, Label* miss, - ElementSupport support_elements, - LanguageMode language_mode); - // KeyedLoadIC_Generic implementation. void GenericElementLoad(Node* receiver, Node* receiver_map, diff --git a/src/ic/handler-configuration-inl.h b/src/ic/handler-configuration-inl.h index f4ddd5eb35..e008de39a4 100644 --- a/src/ic/handler-configuration-inl.h +++ b/src/ic/handler-configuration-inl.h @@ -113,11 +113,6 @@ Handle StoreHandler::StoreNormal(Isolate* isolate) { return handle(Smi::FromInt(config), isolate); } -Handle StoreHandler::StoreProxy(Isolate* isolate) { - int config = KindBits::encode(kProxy); - return handle(Smi::FromInt(config), isolate); -} - Handle StoreHandler::StoreField(Isolate* isolate, Kind kind, int descriptor, FieldIndex field_index, Representation representation, diff --git a/src/ic/handler-configuration.h b/src/ic/handler-configuration.h index f3ded364ee..e970de754c 100644 --- a/src/ic/handler-configuration.h +++ b/src/ic/handler-configuration.h @@ -160,10 +160,8 @@ class StoreHandler { kStoreElement, kStoreField, kStoreConstField, - kTransitionToField, kStoreNormal, - kProxy, - kKindsNumber, // Keep last + kTransitionToField, // TODO(ishell): remove once constant field tracking is done. kTransitionToConstant = kStoreConstField }; @@ -229,9 +227,6 @@ class StoreHandler { // Creates a Smi-handler for storing a property to a slow object. static inline Handle StoreNormal(Isolate* isolate); - // Creates a Smi-handler for storing a property on a proxy. - static inline Handle StoreProxy(Isolate* isolate); - // Creates a Smi-handler for transitioning store to a field. static inline Handle TransitionToField(Isolate* isolate, int descriptor, FieldIndex field_index, diff --git a/src/ic/ic.cc b/src/ic/ic.cc index 9cb2a43c8b..44f1530c43 100644 --- a/src/ic/ic.cc +++ b/src/ic/ic.cc @@ -1223,7 +1223,8 @@ static Handle TryConvertKey(Handle key, Isolate* isolate) { void KeyedLoadIC::UpdateLoadElement(Handle receiver) { Handle receiver_map(receiver->map(), isolate()); - DCHECK(receiver_map->instance_type() != JS_VALUE_TYPE); // Checked by caller. + DCHECK(receiver_map->instance_type() != JS_VALUE_TYPE && + receiver_map->instance_type() != JS_PROXY_TYPE); // Checked by caller. MapHandles target_receiver_maps; TargetMaps(&target_receiver_maps); @@ -1305,9 +1306,6 @@ Handle KeyedLoadIC::LoadElementHandler(Handle receiver_map) { TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_SlowStub); return BUILTIN_CODE(isolate(), KeyedLoadIC_Slow); } - if (instance_type == JS_PROXY_TYPE) { - return LoadHandler::LoadProxy(isolate()); - } ElementsKind elements_kind = receiver_map->elements_kind(); if (IsSloppyArgumentsElementsKind(elements_kind)) { @@ -1380,7 +1378,7 @@ MaybeHandle KeyedLoadIC::Load(Handle object, Object); } else if (FLAG_use_ic && !object->IsAccessCheckNeeded() && !object->IsJSValue()) { - if ((object->IsJSReceiver() && key->IsSmi()) || + if ((object->IsJSObject() && key->IsSmi()) || (object->IsString() && key->IsNumber())) { UpdateLoadElement(Handle::cast(object)); if (is_vector_set()) { @@ -1408,7 +1406,6 @@ bool StoreIC::LookupForWrite(LookupIterator* it, Handle value, JSReceiver::StoreFromKeyed store_mode) { // Disable ICs for non-JSObjects for now. Handle object = it->GetReceiver(); - if (object->IsJSProxy()) return true; if (!object->IsJSObject()) return false; Handle receiver = Handle::cast(object); DCHECK(!receiver->map()->is_deprecated()); @@ -1419,7 +1416,7 @@ bool StoreIC::LookupForWrite(LookupIterator* it, Handle value, case LookupIterator::TRANSITION: UNREACHABLE(); case LookupIterator::JSPROXY: - return true; + return false; case LookupIterator::INTERCEPTOR: { Handle holder = it->GetHolder(); InterceptorInfo* info = holder->GetNamedInterceptor(); @@ -1521,7 +1518,7 @@ MaybeHandle StoreIC::Store(Handle object, Handle name, JSReceiver::StoreFromKeyed store_mode) { // TODO(verwaest): Let SetProperty do the migration, since storing a property // might deprecate the current map again, if value does not fit. - if (MigrateDeprecated(object)) { + if (MigrateDeprecated(object) || object->IsJSProxy()) { Handle result; ASSIGN_RETURN_ON_EXCEPTION( isolate(), result, @@ -1665,45 +1662,6 @@ Handle StoreIC::StoreTransition(Handle receiver_map, return handler_array; } -Handle StoreIC::StoreProxy(Handle receiver_map, - Handle proxy, - Handle receiver, - Handle name) { - Handle smi_handler = StoreHandler::StoreProxy(isolate()); - - if (receiver.is_identical_to(proxy)) { - return smi_handler; - } - - int checks_count = - GetPrototypeCheckCount(isolate(), receiver_map, proxy, name); - - DCHECK_LE(0, checks_count); - DCHECK(!receiver_map->IsJSGlobalObjectMap()); - - Handle validity_cell = - Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); - if (validity_cell.is_null()) { - DCHECK_EQ(0, checks_count); - validity_cell = handle(Smi::kZero, isolate()); - } - - Factory* factory = isolate()->factory(); - Handle holder_cell = factory->NewWeakCell(proxy); - - if (checks_count == 0) { - return factory->NewTuple3(holder_cell, smi_handler, validity_cell, TENURED); - } - Handle handler_array(factory->NewFixedArray( - StoreHandler::kFirstPrototypeIndex + checks_count, TENURED)); - handler_array->set(StoreHandler::kSmiHandlerIndex, *smi_handler); - handler_array->set(StoreHandler::kValidityCellIndex, *validity_cell); - handler_array->set(StoreHandler::kTransitionCellIndex, *holder_cell); - InitPrototypeChecks(isolate(), receiver_map, proxy, name, handler_array, - StoreHandler::kFirstPrototypeIndex); - return handler_array; -} - namespace { Handle StoreGlobal(Isolate* isolate, Handle cell) { @@ -1713,10 +1671,15 @@ Handle StoreGlobal(Isolate* isolate, Handle cell) { } // namespace Handle StoreIC::GetMapIndependentHandler(LookupIterator* lookup) { + DCHECK_NE(LookupIterator::JSPROXY, lookup->state()); + + // This is currently guaranteed by checks in StoreIC::Store. + Handle receiver = Handle::cast(lookup->GetReceiver()); + Handle holder = lookup->GetHolder(); + DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate()); + switch (lookup->state()) { case LookupIterator::TRANSITION: { - Handle holder = lookup->GetHolder(); - auto store_target = lookup->GetStoreTarget(); if (store_target->IsJSGlobalObject()) { TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalTransitionDH); @@ -1740,9 +1703,6 @@ Handle StoreIC::GetMapIndependentHandler(LookupIterator* lookup) { } case LookupIterator::INTERCEPTOR: { - Handle holder = lookup->GetHolder(); - USE(holder); - DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined(isolate())); TRACE_HANDLER_STATS(isolate(), StoreIC_StoreInterceptorStub); StoreInterceptorStub stub(isolate()); @@ -1750,11 +1710,6 @@ Handle StoreIC::GetMapIndependentHandler(LookupIterator* lookup) { } case LookupIterator::ACCESSOR: { - // This is currently guaranteed by checks in StoreIC::Store. - Handle receiver = Handle::cast(lookup->GetReceiver()); - Handle holder = lookup->GetHolder(); - DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate()); - if (!holder->HasFastProperties()) { TRACE_GENERIC_IC("accessor on slow map"); TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); @@ -1805,12 +1760,6 @@ Handle StoreIC::GetMapIndependentHandler(LookupIterator* lookup) { } case LookupIterator::DATA: { - // This is currently guaranteed by checks in StoreIC::Store. - Handle receiver = Handle::cast(lookup->GetReceiver()); - USE(receiver); - Handle holder = lookup->GetHolder(); - DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate()); - DCHECK_EQ(kData, lookup->property_details().kind()); if (lookup->is_dictionary_holder()) { if (holder->IsJSGlobalObject()) { @@ -1843,16 +1792,10 @@ Handle StoreIC::GetMapIndependentHandler(LookupIterator* lookup) { TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); return slow_stub(); } - case LookupIterator::JSPROXY: { - Handle receiver = - Handle::cast(lookup->GetReceiver()); - Handle holder = lookup->GetHolder(); - return StoreIC::StoreProxy(receiver_map(), holder, receiver, - lookup->name()); - } case LookupIterator::INTEGER_INDEXED_EXOTIC: case LookupIterator::ACCESS_CHECK: + case LookupIterator::JSPROXY: case LookupIterator::NOT_FOUND: UNREACHABLE(); } @@ -1933,8 +1876,7 @@ void KeyedStoreIC::UpdateStoreElement(Handle receiver_map, // transition to a different GetNonTransitioningStoreMode IC that handles a // superset of the original IC. Handle those here if the receiver map hasn't // changed or it has transitioned to a more general kind. - KeyedAccessStoreMode old_store_mode; - old_store_mode = GetKeyedAccessStoreMode(); + KeyedAccessStoreMode old_store_mode = GetKeyedAccessStoreMode(); Handle previous_receiver_map = target_receiver_maps.at(0); if (state() == MONOMORPHIC) { Handle transitioned_receiver_map = receiver_map; @@ -2069,10 +2011,6 @@ Handle KeyedStoreIC::StoreElementHandler( store_mode == STORE_NO_TRANSITION_HANDLE_COW); DCHECK(!receiver_map->DictionaryElementsInPrototypeChainOnly()); - if (receiver_map->IsJSProxyMap()) { - return StoreHandler::StoreProxy(isolate()); - } - ElementsKind elements_kind = receiver_map->elements_kind(); bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; Handle stub; @@ -2284,17 +2222,15 @@ MaybeHandle KeyedStoreIC::Store(Handle object, bool is_arguments = false; bool key_is_valid_index = false; KeyedAccessStoreMode store_mode = STANDARD_STORE; - if (use_ic && object->IsJSReceiver()) { - Handle receiver = Handle::cast(object); + if (use_ic && object->IsJSObject()) { + Handle receiver = Handle::cast(object); old_receiver_map = handle(receiver->map(), isolate()); is_arguments = receiver->IsJSArgumentsObject(); - bool is_proxy = receiver->IsJSProxy(); - key_is_valid_index = key->IsSmi() && Smi::ToInt(*key) >= 0; - if (!is_arguments && !is_proxy) { + if (!is_arguments) { + key_is_valid_index = key->IsSmi() && Smi::ToInt(*key) >= 0; if (key_is_valid_index) { uint32_t index = static_cast(Smi::ToInt(*key)); - Handle receiver_object = Handle::cast(object); - store_mode = GetStoreMode(receiver_object, index, value); + store_mode = GetStoreMode(receiver, index, value); } } } diff --git a/src/ic/ic.h b/src/ic/ic.h index c4af5b1496..f2e2602447 100644 --- a/src/ic/ic.h +++ b/src/ic/ic.h @@ -359,9 +359,6 @@ class StoreIC : public IC { Handle holder, Handle transition, Handle name); - Handle StoreProxy(Handle receiver_map, Handle proxy, - Handle receiver, Handle name); - friend class IC; bool created_new_transition_ = false; diff --git a/src/ic/keyed-store-generic.cc b/src/ic/keyed-store-generic.cc index f9bca900ab..d2a82f7077 100644 --- a/src/ic/keyed-store-generic.cc +++ b/src/ic/keyed-store-generic.cc @@ -841,8 +841,7 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore( BIND(&found_handler); { Comment("KeyedStoreGeneric found transition handler"); - HandleStoreICHandlerCase(p, var_handler.value(), notfound, - language_mode); + HandleStoreICHandlerCase(p, var_handler.value(), notfound); } } } @@ -950,8 +949,7 @@ void KeyedStoreGenericAssembler::EmitGenericPropertyStore( BIND(&found_handler); { Comment("KeyedStoreGeneric found handler"); - HandleStoreICHandlerCase(p, var_handler.value(), &stub_cache_miss, - language_mode); + HandleStoreICHandlerCase(p, var_handler.value(), &stub_cache_miss); } BIND(&stub_cache_miss); { @@ -1022,14 +1020,13 @@ void KeyedStoreGenericAssembler::StoreIC_Uninitialized( Node* vector = Parameter(Descriptor::kVector); Node* context = Parameter(Descriptor::kContext); - Label miss(this), if_proxy(this, Label::kDeferred); + Label miss(this); GotoIf(TaggedIsSmi(receiver), &miss); Node* receiver_map = LoadMap(receiver); Node* instance_type = LoadMapInstanceType(receiver_map); - GotoIf(Word32Equal(instance_type, Int32Constant(JS_PROXY_TYPE)), &if_proxy); // Receivers requiring non-standard element accesses (interceptors, access - // checks, strings and string wrappers) are handled in the runtime. + // checks, strings and string wrappers, proxies) are handled in the runtime. GotoIf(Int32LessThanOrEqual(instance_type, Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), &miss); @@ -1043,12 +1040,6 @@ void KeyedStoreGenericAssembler::StoreIC_Uninitialized( EmitGenericPropertyStore(receiver, receiver_map, &p, &miss, language_mode, kDontUseStubCache); - BIND(&if_proxy); - { - CallBuiltin(Builtins::kProxySetProperty, context, receiver, name, value, - receiver, SmiConstant(language_mode)); - Return(value); - } BIND(&miss); { // Undo the optimistic state transition. diff --git a/src/lookup.cc b/src/lookup.cc index 75f008f105..36f58e0970 100644 --- a/src/lookup.cc +++ b/src/lookup.cc @@ -13,42 +13,12 @@ namespace v8 { namespace internal { -// static -LookupIterator LookupIterator::PropertyOrElement( - Isolate* isolate, Handle receiver, Handle key, - bool* success, Handle holder, Configuration configuration) { - uint32_t index = 0; - if (key->ToArrayIndex(&index)) { - *success = true; - return LookupIterator(isolate, receiver, index, holder, configuration); - } - - Handle name; - *success = Object::ToName(isolate, key).ToHandle(&name); - if (!*success) { - DCHECK(isolate->has_pending_exception()); - // Return an unusable dummy. - return LookupIterator(receiver, isolate->factory()->empty_string()); - } - - if (name->AsArrayIndex(&index)) { - LookupIterator it(isolate, receiver, index, holder, configuration); - // Here we try to avoid having to rebuild the string later - // by storing it on the indexed LookupIterator. - it.name_ = name; - return it; - } - - return LookupIterator(receiver, name, holder, configuration); -} - // static LookupIterator LookupIterator::PropertyOrElement(Isolate* isolate, Handle receiver, Handle key, bool* success, Configuration configuration) { - // TODO(mslekova): come up with better way to avoid duplication uint32_t index = 0; if (key->ToArrayIndex(&index)) { *success = true; diff --git a/src/lookup.h b/src/lookup.h index 25c5a6cc3b..8fa55bd188 100644 --- a/src/lookup.h +++ b/src/lookup.h @@ -126,11 +126,6 @@ class V8_EXPORT_PRIVATE LookupIterator final BASE_EMBEDDED { return LookupIterator(receiver, name, holder, configuration); } - static LookupIterator PropertyOrElement( - Isolate* isolate, Handle receiver, Handle key, - bool* success, Handle holder, - Configuration configuration = DEFAULT); - static LookupIterator PropertyOrElement( Isolate* isolate, Handle receiver, Handle key, bool* success, Configuration configuration = DEFAULT); diff --git a/src/objects.cc b/src/objects.cc index b3c71938ff..6cb77e4c25 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -1106,7 +1106,7 @@ MaybeHandle JSProxy::GetProperty(Isolate* isolate, Execution::Call(isolate, trap, handler, arraysize(args), args), Object); MaybeHandle result = - JSProxy::CheckGetSetTrapResult(isolate, name, target, trap_result, kGet); + JSProxy::CheckGetTrapResult(isolate, name, target, trap_result); if (result.is_null()) { return result; } @@ -1116,11 +1116,10 @@ MaybeHandle JSProxy::GetProperty(Isolate* isolate, } // static -MaybeHandle JSProxy::CheckGetSetTrapResult(Isolate* isolate, - Handle name, - Handle target, - Handle trap_result, - AccessKind access_kind) { +MaybeHandle JSProxy::CheckGetTrapResult(Isolate* isolate, + Handle name, + Handle target, + Handle trap_result) { // 9. Let targetDesc be ? target.[[GetOwnProperty]](P). PropertyDescriptor target_desc; Maybe target_found = @@ -1137,43 +1136,24 @@ MaybeHandle JSProxy::CheckGetSetTrapResult(Isolate* isolate, !target_desc.writable() && !trap_result->SameValue(*target_desc.value()); if (inconsistent) { - if (access_kind == kGet) { - THROW_NEW_ERROR( - isolate, - NewTypeError(MessageTemplate::kProxyGetNonConfigurableData, name, - target_desc.value(), trap_result), - Object); - } else { - isolate->Throw(*isolate->factory()->NewTypeError( - MessageTemplate::kProxySetFrozenData, name)); - return MaybeHandle(); - } + THROW_NEW_ERROR( + isolate, NewTypeError(MessageTemplate::kProxyGetNonConfigurableData, + name, target_desc.value(), trap_result), + Object); } // 10.b. If IsAccessorDescriptor(targetDesc) and targetDesc.[[Configurable]] // is false and targetDesc.[[Get]] is undefined, then // 10.b.i. If trapResult is not undefined, throw a TypeError exception. - if (access_kind == kGet) { - inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) && - !target_desc.configurable() && - target_desc.get()->IsUndefined(isolate) && - !trap_result->IsUndefined(isolate); - } else { - inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) && - !target_desc.configurable() && - target_desc.set()->IsUndefined(isolate); - } + inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) && + !target_desc.configurable() && + target_desc.get()->IsUndefined(isolate) && + !trap_result->IsUndefined(isolate); if (inconsistent) { - if (access_kind == kGet) { - THROW_NEW_ERROR( - isolate, - NewTypeError(MessageTemplate::kProxyGetNonConfigurableAccessor, - name, trap_result), - Object); - } else { - isolate->Throw(*isolate->factory()->NewTypeError( - MessageTemplate::kProxySetFrozenAccessor, name)); - return MaybeHandle(); - } + THROW_NEW_ERROR( + isolate, + NewTypeError(MessageTemplate::kProxyGetNonConfigurableAccessor, name, + trap_result), + Object); } } return isolate->factory()->undefined_value(); @@ -5547,11 +5527,29 @@ Maybe JSProxy::SetProperty(Handle proxy, Handle name, trap_name, name)); } - MaybeHandle result = - JSProxy::CheckGetSetTrapResult(isolate, name, target, value, kSet); - - if (result.is_null()) { - return Nothing(); + // Enforce the invariant. + PropertyDescriptor target_desc; + Maybe owned = + JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc); + MAYBE_RETURN(owned, Nothing()); + if (owned.FromJust()) { + bool inconsistent = PropertyDescriptor::IsDataDescriptor(&target_desc) && + !target_desc.configurable() && + !target_desc.writable() && + !value->SameValue(*target_desc.value()); + if (inconsistent) { + isolate->Throw(*isolate->factory()->NewTypeError( + MessageTemplate::kProxySetFrozenData, name)); + return Nothing(); + } + inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) && + !target_desc.configurable() && + target_desc.set()->IsUndefined(isolate); + if (inconsistent) { + isolate->Throw(*isolate->factory()->NewTypeError( + MessageTemplate::kProxySetFrozenAccessor, name)); + return Nothing(); + } } return Just(true); } diff --git a/src/objects.h b/src/objects.h index aa109b358a..678b01b659 100644 --- a/src/objects.h +++ b/src/objects.h @@ -6046,13 +6046,10 @@ class JSProxy: public JSReceiver { Isolate* isolate, Handle proxy, Handle name, Handle receiver, bool* was_found); - enum AccessKind { kGet, kSet }; - - static MaybeHandle CheckGetSetTrapResult(Isolate* isolate, - Handle name, - Handle target, - Handle trap_result, - AccessKind access_kind); + static MaybeHandle CheckGetTrapResult(Isolate* isolate, + Handle name, + Handle target, + Handle trap_result); // ES6 9.5.9 MUST_USE_RESULT static Maybe SetProperty(Handle proxy, diff --git a/src/runtime/runtime-proxy.cc b/src/runtime/runtime-proxy.cc index dcf0a6715a..7e38c59fb5 100644 --- a/src/runtime/runtime-proxy.cc +++ b/src/runtime/runtime-proxy.cc @@ -51,47 +51,24 @@ RUNTIME_FUNCTION(Runtime_GetPropertyWithReceiver) { DCHECK_EQ(3, args.length()); CONVERT_ARG_HANDLE_CHECKED(JSReceiver, holder, 0); - CONVERT_ARG_HANDLE_CHECKED(Object, name, 1); + CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 2); - bool success; - LookupIterator it = LookupIterator::PropertyOrElement(isolate, receiver, name, - &success, holder); + LookupIterator it = + LookupIterator::PropertyOrElement(isolate, receiver, name, holder); RETURN_RESULT_OR_FAILURE(isolate, Object::GetProperty(&it)); } -RUNTIME_FUNCTION(Runtime_SetPropertyWithReceiver) { +RUNTIME_FUNCTION(Runtime_CheckProxyGetTrapResult) { HandleScope scope(isolate); - DCHECK_EQ(5, args.length()); - CONVERT_ARG_HANDLE_CHECKED(JSReceiver, holder, 0); - CONVERT_ARG_HANDLE_CHECKED(Object, name, 1); - CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); - CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 3); - CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 4); - - bool success; - LookupIterator it = LookupIterator::PropertyOrElement(isolate, receiver, name, - &success, holder); - - Maybe result = Object::SetSuperProperty( - &it, value, language_mode, Object::MAY_BE_STORE_FROM_KEYED); - MAYBE_RETURN(result, isolate->heap()->exception()); - return *isolate->factory()->ToBoolean(result.FromJust()); -} - -RUNTIME_FUNCTION(Runtime_CheckProxyGetSetTrapResult) { - HandleScope scope(isolate); - - DCHECK_EQ(4, args.length()); + DCHECK_EQ(3, args.length()); CONVERT_ARG_HANDLE_CHECKED(Name, name, 0); CONVERT_ARG_HANDLE_CHECKED(JSReceiver, target, 1); CONVERT_ARG_HANDLE_CHECKED(Object, trap_result, 2); - CONVERT_NUMBER_CHECKED(int64_t, access_kind, Int64, args[3]); - RETURN_RESULT_OR_FAILURE(isolate, JSProxy::CheckGetSetTrapResult( - isolate, name, target, trap_result, - JSProxy::AccessKind(access_kind))); + RETURN_RESULT_OR_FAILURE( + isolate, JSProxy::CheckGetTrapResult(isolate, name, target, trap_result)); } RUNTIME_FUNCTION(Runtime_CheckProxyHasTrap) { diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index 765934dbbb..8a58b537f3 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -469,9 +469,8 @@ namespace internal { F(JSProxyGetHandler, 1, 1) \ F(JSProxyRevoke, 1, 1) \ F(GetPropertyWithReceiver, 2, 1) \ - F(CheckProxyHasTrap, 2, 1) \ - F(SetPropertyWithReceiver, 5, 1) \ - F(CheckProxyGetSetTrapResult, 2, 1) + F(CheckProxyGetTrapResult, 2, 1) \ + F(CheckProxyHasTrap, 2, 1) #define FOR_EACH_INTRINSIC_REGEXP(F) \ F(IsRegExp, 1, 1) \ diff --git a/src/v8.gyp b/src/v8.gyp index 14fdeedfcc..d609ef30b1 100644 --- a/src/v8.gyp +++ b/src/v8.gyp @@ -208,6 +208,8 @@ 'builtins/builtins-promise-gen.h', 'builtins/builtins-proxy-gen.cc', 'builtins/builtins-proxy-gen.h', + 'builtins/builtins-proxy-helpers-gen.cc', + 'builtins/builtins-proxy-helpers-gen.h', 'builtins/builtins-regexp-gen.cc', 'builtins/builtins-regexp-gen.h', 'builtins/builtins-sharedarraybuffer-gen.cc', diff --git a/test/mjsunit/es6/proxies-get.js b/test/mjsunit/es6/proxies-get.js index f52ae1aa7e..4f7b2d0be4 100644 --- a/test/mjsunit/es6/proxies-get.js +++ b/test/mjsunit/es6/proxies-get.js @@ -193,6 +193,7 @@ 'Error from proxy getOwnPropertyDescriptor trap'); })(); + (function testGetPropertyDetailsBailout2() { var obj = {}; Object.defineProperty(obj, 'prop', { @@ -210,13 +211,3 @@ " property on the proxy target but the proxy did not return its actual" + " value (expected '53' but got '42')"); })(); - -(function test32BitIndex() { - var index = (1 << 31) + 1; - var obj = {}; - obj[index] = 42; - var p = new Proxy(obj, {}); - for (var i = 0; i < 3; ++i) { - assertEquals(42, p[index]); - } -})(); diff --git a/test/mjsunit/es6/proxies-set.js b/test/mjsunit/es6/proxies-set.js index d56cec52f9..19f39f9a65 100644 --- a/test/mjsunit/es6/proxies-set.js +++ b/test/mjsunit/es6/proxies-set.js @@ -308,101 +308,3 @@ TestTrapReceiverArgument(strictReflectSet); } } })(); - - -function TestTargetProxy(mySet) { - var q = new Proxy({}, {}); - var proxy = new Proxy(q, { - set: function(t, k, v) { - return Reflect.set(t, k, v); - } - }); - - for (var p of properties) { - assertTrueIf(mySet.returnsBool, mySet(proxy, p, 42)); - assertSame(42, q[p]); - } -}; - -TestTargetProxy(sloppyDefaultSet); -TestTargetProxy(sloppyReflectSet); -TestTargetProxy(strictDefaultSet); -TestTargetProxy(strictReflectSet); - - -(function TestAccessorNoSet() { - var target = { - }; - Object.defineProperty(target, 'prop', { - get: function() { - return 42; - }, - configurable: false - }) - var handler = { - set: function() { return true; } - } - var proxy = new Proxy(target, handler); - assertThrows(function() { proxy.prop = 0; }, TypeError); -})(); - -(function TestProxyInPrototype() { - var handler = { - set: function(t, k, v) { - Reflect.set(t, k, v); - } - }; - var obj = {}; - var proxy = new Proxy(obj, handler); - var o = Object.create(proxy); - - for (var i = 0; i < 3; ++i) { - o.prop = 42 + i; - assertEquals(42 + i, obj.prop); - } -})(); - -(function TestProxyInPrototypeNoTrap() { - var handler = { - }; - var obj = {}; - var proxy = new Proxy(obj, handler); - var o = Object.create(proxy); - - for (var i = 0; i < 3; ++i) { - o.prop = 42 + i; - assertEquals(42 + i, o.prop); - assertEquals(undefined, obj.prop); - } -})(); - -// Note: this case is currently handled by runtime. -(function TestDifferentHolder() { - var obj = { - '1337': 100 - }; - var handler = { - set(target, name, value, receiver) { - if (name != '1337') return Reflect.set(target, name, value, receiver); - - assertSame(target, obj); - assertSame(receiver, p); - return target[name] = value; - } - }; - var p = new Proxy(obj, handler); - for (var i = 0; i < 3; ++i) { - assertEquals(42, p[1337] = 42); - } -})(); - -(function test32BitIndex() { - var index = (1 << 31) + 1; - var obj = {}; - obj[index] = 42; - var p = new Proxy(obj, {}); - for (var i = 0; i < 3; ++i) { - p[index] = 100; - assertEquals(100, obj[index]); - } -})();