Commit 72e8a978 authored by gsathya's avatar gsathya Committed by Commit bot

[pattern rewriter] Only desugar to call %ToName on computed properties

Convert strings to numbers if possible in the runtime call and store
in excluded property list.

BUG=v8:5549

Review-Url: https://codereview.chromium.org/2639333004
Cr-Commit-Position: refs/heads/master@{#42581}
parent 380b720d
...@@ -2003,7 +2003,8 @@ Maybe<bool> JSReceiver::HasInPrototypeChain(Isolate* isolate, ...@@ -2003,7 +2003,8 @@ Maybe<bool> JSReceiver::HasInPrototypeChain(Isolate* isolate,
namespace { namespace {
bool HasExcludedProperty(const ScopedVector<Handle<Name>>* excluded_properties, bool HasExcludedProperty(
const ScopedVector<Handle<Object>>* excluded_properties,
Handle<Object> search_element) { Handle<Object> search_element) {
// TODO(gsathya): Change this to be a hashtable. // TODO(gsathya): Change this to be a hashtable.
for (int i = 0; i < excluded_properties->length(); i++) { for (int i = 0; i < excluded_properties->length(); i++) {
...@@ -2017,7 +2018,7 @@ bool HasExcludedProperty(const ScopedVector<Handle<Name>>* excluded_properties, ...@@ -2017,7 +2018,7 @@ bool HasExcludedProperty(const ScopedVector<Handle<Name>>* excluded_properties,
MUST_USE_RESULT Maybe<bool> FastAssign( MUST_USE_RESULT Maybe<bool> FastAssign(
Handle<JSReceiver> target, Handle<Object> source, Handle<JSReceiver> target, Handle<Object> source,
const ScopedVector<Handle<Name>>* excluded_properties, bool use_set) { const ScopedVector<Handle<Object>>* excluded_properties, bool use_set) {
// Non-empty strings are the only non-JSReceivers that need to be handled // Non-empty strings are the only non-JSReceivers that need to be handled
// explicitly by Object.assign. // explicitly by Object.assign.
if (!source->IsJSReceiver()) { if (!source->IsJSReceiver()) {
...@@ -2113,7 +2114,7 @@ MUST_USE_RESULT Maybe<bool> FastAssign( ...@@ -2113,7 +2114,7 @@ MUST_USE_RESULT Maybe<bool> FastAssign(
// static // static
Maybe<bool> JSReceiver::SetOrCopyDataProperties( Maybe<bool> JSReceiver::SetOrCopyDataProperties(
Isolate* isolate, Handle<JSReceiver> target, Handle<Object> source, Isolate* isolate, Handle<JSReceiver> target, Handle<Object> source,
const ScopedVector<Handle<Name>>* excluded_properties, bool use_set) { const ScopedVector<Handle<Object>>* excluded_properties, bool use_set) {
Maybe<bool> fast_assign = Maybe<bool> fast_assign =
FastAssign(target, source, excluded_properties, use_set); FastAssign(target, source, excluded_properties, use_set);
if (fast_assign.IsNothing()) return Nothing<bool>(); if (fast_assign.IsNothing()) return Nothing<bool>();
...@@ -2125,7 +2126,7 @@ Maybe<bool> JSReceiver::SetOrCopyDataProperties( ...@@ -2125,7 +2126,7 @@ Maybe<bool> JSReceiver::SetOrCopyDataProperties(
ASSIGN_RETURN_ON_EXCEPTION_VALUE( ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, keys, isolate, keys,
KeyAccumulator::GetKeys(from, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES, KeyAccumulator::GetKeys(from, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
GetKeysConversion::kConvertToString), GetKeysConversion::kKeepNumbers),
Nothing<bool>()); Nothing<bool>());
// 4. Repeat for each element nextKey of keys in List order, // 4. Repeat for each element nextKey of keys in List order,
...@@ -6676,7 +6677,6 @@ bool PropertyKeyToArrayLength(Handle<Object> value, uint32_t* length) { ...@@ -6676,7 +6677,6 @@ bool PropertyKeyToArrayLength(Handle<Object> value, uint32_t* length) {
return false; return false;
} }
bool PropertyKeyToArrayIndex(Handle<Object> index_obj, uint32_t* output) { bool PropertyKeyToArrayIndex(Handle<Object> index_obj, uint32_t* output) {
return PropertyKeyToArrayLength(index_obj, output) && *output != kMaxUInt32; return PropertyKeyToArrayLength(index_obj, output) && *output != kMaxUInt32;
} }
......
...@@ -2011,7 +2011,7 @@ class JSReceiver: public HeapObject { ...@@ -2011,7 +2011,7 @@ class JSReceiver: public HeapObject {
// maybe_excluded_properties list. // maybe_excluded_properties list.
MUST_USE_RESULT static Maybe<bool> SetOrCopyDataProperties( MUST_USE_RESULT static Maybe<bool> SetOrCopyDataProperties(
Isolate* isolate, Handle<JSReceiver> target, Handle<Object> source, Isolate* isolate, Handle<JSReceiver> target, Handle<Object> source,
const ScopedVector<Handle<Name>>* excluded_properties = nullptr, const ScopedVector<Handle<Object>>* excluded_properties = nullptr,
bool use_set = true); bool use_set = true);
// Implementation of [[HasProperty]], ECMA-262 5th edition, section 8.12.6. // Implementation of [[HasProperty]], ECMA-262 5th edition, section 8.12.6.
......
...@@ -361,12 +361,11 @@ void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern, ...@@ -361,12 +361,11 @@ void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern,
if (property->kind() == ObjectLiteralProperty::Kind::SPREAD) { if (property->kind() == ObjectLiteralProperty::Kind::SPREAD) {
// var { y, [x++]: a, ...c } = temp // var { y, [x++]: a, ...c } = temp
// becomes // becomes
// var temp1 = %ToName('y'); // var y = temp.y;
// var y = temp[temp1] // var temp1 = %ToName(x++);
// var temp2 = %ToName(x++); // var a = temp[temp1];
// var a = temp[temp2];
// var c; // var c;
// c = %CopyDataPropertiesWithExcludedProperties(temp, temp1, temp2); // c = %CopyDataPropertiesWithExcludedProperties(temp, "y", temp1);
value = factory()->NewCallRuntime( value = factory()->NewCallRuntime(
Runtime::kCopyDataPropertiesWithExcludedProperties, Runtime::kCopyDataPropertiesWithExcludedProperties,
rest_runtime_callargs, kNoSourcePosition); rest_runtime_callargs, kNoSourcePosition);
...@@ -379,17 +378,23 @@ void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern, ...@@ -379,17 +378,23 @@ void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern,
RewriteParameterScopes(key); RewriteParameterScopes(key);
} }
// TODO(gsathya): Skip %ToName runtime call for literals.
if (pattern->has_rest_property()) { if (pattern->has_rest_property()) {
Expression* excluded_property = key;
if (property->is_computed_name()) {
DCHECK(!key->IsPropertyName() || !key->IsNumberLiteral());
auto args = new (zone()) ZoneList<Expression*>(1, zone()); auto args = new (zone()) ZoneList<Expression*>(1, zone());
args->Add(key, zone()); args->Add(key, zone());
auto to_name_key = CreateTempVar(factory()->NewCallRuntime( auto to_name_key = CreateTempVar(factory()->NewCallRuntime(
Runtime::kToName, args, kNoSourcePosition)); Runtime::kToName, args, kNoSourcePosition));
key = factory()->NewVariableProxy(to_name_key); key = factory()->NewVariableProxy(to_name_key);
excluded_property = factory()->NewVariableProxy(to_name_key);
} else {
DCHECK(key->IsPropertyName() || key->IsNumberLiteral());
}
DCHECK(rest_runtime_callargs != nullptr); DCHECK(rest_runtime_callargs != nullptr);
rest_runtime_callargs->Add(factory()->NewVariableProxy(to_name_key), rest_runtime_callargs->Add(excluded_property, zone());
zone());
} }
value = factory()->NewProperty(factory()->NewVariableProxy(temp), key, value = factory()->NewProperty(factory()->NewVariableProxy(temp), key,
......
...@@ -779,9 +779,20 @@ RUNTIME_FUNCTION(Runtime_CopyDataPropertiesWithExcludedProperties) { ...@@ -779,9 +779,20 @@ RUNTIME_FUNCTION(Runtime_CopyDataPropertiesWithExcludedProperties) {
return isolate->heap()->undefined_value(); return isolate->heap()->undefined_value();
} }
ScopedVector<Handle<Name>> excluded_properties(args.length() - 1); ScopedVector<Handle<Object>> excluded_properties(args.length() - 1);
for (int i = 1; i < args.length(); i++) { for (int i = 1; i < args.length(); i++) {
excluded_properties[i - 1] = args.at<Name>(i); Handle<Object> property = args.at(i);
uint32_t property_num;
// We convert string to number if possible, in cases of computed
// properties resolving to numbers, which would've been strings
// instead because of our call to %ToName() in the desugaring for
// computed properties.
if (property->IsString() &&
String::cast(*property)->AsArrayIndex(&property_num)) {
property = isolate->factory()->NewNumberFromUint(property_num);
}
excluded_properties[i - 1] = property;
} }
Handle<JSObject> target = Handle<JSObject> target =
......
...@@ -42,6 +42,11 @@ assertEquals({ a: 1 }, x); ...@@ -42,6 +42,11 @@ assertEquals({ a: 1 }, x);
assertEquals(key, 2); assertEquals(key, 2);
assertEquals(1, y); assertEquals(1, y);
var key = '1';
var {[key]: y, ...x} = {1: 1, a: 1};
assertEquals({a: 1}, x);
assertEquals(1, y);
function example({a, ...rest}, { b = rest }) { function example({a, ...rest}, { b = rest }) {
assertEquals(1, a); assertEquals(1, a);
assertEquals({ b: 2, c: 3}, rest); assertEquals({ b: 2, c: 3}, rest);
...@@ -56,6 +61,13 @@ var y = { ...@@ -56,6 +61,13 @@ var y = {
}; };
assertEquals(y.a, 3); assertEquals(y.a, 3);
var {...y} = {
get a() {
return 1
}
};
assertEquals({a: 1}, y);
var x = { var x = {
get a() { throw new Error(); }, get a() { throw new Error(); },
}; };
...@@ -120,3 +132,28 @@ assertEquals({ 0: { x: 1} }, z); ...@@ -120,3 +132,28 @@ assertEquals({ 0: { x: 1} }, z);
var {...{x}} = { x: 1}; var {...{x}} = { x: 1};
assertEquals(1, x); assertEquals(1, x);
var {4294967297: y, ...x} = {4294967297: 1, x: 1};
assertEquals(1, y);
assertEquals({x: 1}, x);
var obj = {
[Symbol.toPrimitive]() {
return 1;
}
};
var {[obj]: y, ...x} = {1: 1, x: 1};
assertEquals(1, y);
assertEquals({x: 1}, x);
var {[null]: y, ...x} = {null: 1, x: 1};
assertEquals(1, y);
assertEquals({x: 1}, x);
var {[true]: y, ...x} = {true: 1, x: 1};
assertEquals(1, y);
assertEquals({x: 1}, x);
var {[false]: y, ...x} = {false: 1, x: 1};
assertEquals(1, y);
assertEquals({x: 1}, x);
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