From: dslomov@chromium.org Date: Mon, 13 Oct 2014 12:46:46 +0000 (+0000) Subject: Support for super assignments in for..in. X-Git-Tag: upstream/4.7.83~6406 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=952690a148e35f9dd87b1478bc7b9989ad091211;p=platform%2Fupstream%2Fv8.git Support for super assignments in for..in. R=ishell@chromium.org, arv@chromium.org BUG=v8:3330 LOG=N Review URL: https://codereview.chromium.org/639243003 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24560 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index 369f714..de7d627 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -2514,16 +2514,8 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, void FullCodeGenerator::EmitAssignment(Expression* expr) { DCHECK(expr->IsValidReferenceExpression()); - // Left-hand side can only be a property, a global or a (parameter or local) - // slot. - enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; - LhsKind assign_type = VARIABLE; Property* prop = expr->AsProperty(); - if (prop != NULL) { - assign_type = (prop->key()->IsPropertyName()) - ? NAMED_PROPERTY - : KEYED_PROPERTY; - } + LhsKind assign_type = GetAssignType(prop); switch (assign_type) { case VARIABLE: { @@ -2542,6 +2534,42 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { CallStoreIC(); break; } + case NAMED_SUPER_PROPERTY: { + __ Push(r0); + VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); + EmitLoadHomeObject(prop->obj()->AsSuperReference()); + // stack: value, this; r0: home_object + Register scratch = r2; + Register scratch2 = r3; + __ mov(scratch, result_register()); // home_object + __ ldr(r0, MemOperand(sp, kPointerSize)); // value + __ ldr(scratch2, MemOperand(sp, 0)); // this + __ str(scratch2, MemOperand(sp, kPointerSize)); // this + __ str(scratch, MemOperand(sp, 0)); // home_object + // stack: this, home_object; r0: value + EmitNamedSuperPropertyStore(prop); + break; + } + case KEYED_SUPER_PROPERTY: { + __ Push(r0); + VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); + EmitLoadHomeObject(prop->obj()->AsSuperReference()); + __ Push(result_register()); + VisitForAccumulatorValue(prop->key()); + Register scratch = r2; + Register scratch2 = r3; + __ ldr(scratch2, MemOperand(sp, 2 * kPointerSize)); // value + // stack: value, this, home_object; r0: key, r3: value + __ ldr(scratch, MemOperand(sp, kPointerSize)); // this + __ str(scratch, MemOperand(sp, 2 * kPointerSize)); + __ ldr(scratch, MemOperand(sp, 0)); // home_object + __ str(scratch, MemOperand(sp, kPointerSize)); + __ str(r0, MemOperand(sp, 0)); + __ Move(r0, scratch2); + // stack: this, home_object, key; r0: value. + EmitKeyedSuperPropertyStore(prop); + break; + } case KEYED_PROPERTY: { __ push(r0); // Preserve value. VisitForStackValue(prop->obj()); diff --git a/src/arm64/full-codegen-arm64.cc b/src/arm64/full-codegen-arm64.cc index eba9ad9..5911e69 100644 --- a/src/arm64/full-codegen-arm64.cc +++ b/src/arm64/full-codegen-arm64.cc @@ -2172,16 +2172,8 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, void FullCodeGenerator::EmitAssignment(Expression* expr) { DCHECK(expr->IsValidReferenceExpression()); - // Left-hand side can only be a property, a global or a (parameter or local) - // slot. - enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; - LhsKind assign_type = VARIABLE; Property* prop = expr->AsProperty(); - if (prop != NULL) { - assign_type = (prop->key()->IsPropertyName()) - ? NAMED_PROPERTY - : KEYED_PROPERTY; - } + LhsKind assign_type = GetAssignType(prop); switch (assign_type) { case VARIABLE: { @@ -2202,6 +2194,42 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { CallStoreIC(); break; } + case NAMED_SUPER_PROPERTY: { + __ Push(x0); + VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); + EmitLoadHomeObject(prop->obj()->AsSuperReference()); + // stack: value, this; x0: home_object + Register scratch = x10; + Register scratch2 = x11; + __ mov(scratch, result_register()); // home_object + __ Peek(x0, kPointerSize); // value + __ Peek(scratch2, 0); // this + __ Poke(scratch2, kPointerSize); // this + __ Poke(scratch, 0); // home_object + // stack: this, home_object; x0: value + EmitNamedSuperPropertyStore(prop); + break; + } + case KEYED_SUPER_PROPERTY: { + __ Push(x0); + VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); + EmitLoadHomeObject(prop->obj()->AsSuperReference()); + __ Push(result_register()); + VisitForAccumulatorValue(prop->key()); + Register scratch = x10; + Register scratch2 = x11; + __ Peek(scratch2, 2 * kPointerSize); // value + // stack: value, this, home_object; x0: key, x11: value + __ Peek(scratch, kPointerSize); // this + __ Poke(scratch, 2 * kPointerSize); + __ Peek(scratch, 0); // home_object + __ Poke(scratch, kPointerSize); + __ Poke(x0, 0); + __ Move(x0, scratch2); + // stack: this, home_object, key; x0: value. + EmitKeyedSuperPropertyStore(prop); + break; + } case KEYED_PROPERTY: { __ Push(x0); // Preserve value. VisitForStackValue(prop->obj()); diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index fa68870..ad838b9 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -2430,16 +2430,8 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, void FullCodeGenerator::EmitAssignment(Expression* expr) { DCHECK(expr->IsValidReferenceExpression()); - // Left-hand side can only be a property, a global or a (parameter or local) - // slot. - enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; - LhsKind assign_type = VARIABLE; Property* prop = expr->AsProperty(); - if (prop != NULL) { - assign_type = (prop->key()->IsPropertyName()) - ? NAMED_PROPERTY - : KEYED_PROPERTY; - } + LhsKind assign_type = GetAssignType(prop); switch (assign_type) { case VARIABLE: { @@ -2458,6 +2450,42 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { CallStoreIC(); break; } + case NAMED_SUPER_PROPERTY: { + __ push(eax); + VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); + EmitLoadHomeObject(prop->obj()->AsSuperReference()); + // stack: value, this; eax: home_object + Register scratch = ecx; + Register scratch2 = edx; + __ mov(scratch, result_register()); // home_object + __ mov(eax, MemOperand(esp, kPointerSize)); // value + __ mov(scratch2, MemOperand(esp, 0)); // this + __ mov(MemOperand(esp, kPointerSize), scratch2); // this + __ mov(MemOperand(esp, 0), scratch); // home_object + // stack: this, home_object. eax: value + EmitNamedSuperPropertyStore(prop); + break; + } + case KEYED_SUPER_PROPERTY: { + __ push(eax); + VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); + EmitLoadHomeObject(prop->obj()->AsSuperReference()); + __ push(result_register()); + VisitForAccumulatorValue(prop->key()); + Register scratch = ecx; + Register scratch2 = edx; + __ mov(scratch2, MemOperand(esp, 2 * kPointerSize)); // value + // stack: value, this, home_object; eax: key, edx: value + __ mov(scratch, MemOperand(esp, kPointerSize)); // this + __ mov(MemOperand(esp, 2 * kPointerSize), scratch); + __ mov(scratch, MemOperand(esp, 0)); // home_object + __ mov(MemOperand(esp, kPointerSize), scratch); + __ mov(MemOperand(esp, 0), eax); + __ mov(eax, scratch2); + // stack: this, home_object, key; eax: value. + EmitKeyedSuperPropertyStore(prop); + break; + } case KEYED_PROPERTY: { __ push(eax); // Preserve value. VisitForStackValue(prop->obj()); diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc index 0d93114..d4ed767 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc @@ -2429,16 +2429,8 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, void FullCodeGenerator::EmitAssignment(Expression* expr) { DCHECK(expr->IsValidReferenceExpression()); - // Left-hand side can only be a property, a global or a (parameter or local) - // slot. - enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; - LhsKind assign_type = VARIABLE; Property* prop = expr->AsProperty(); - if (prop != NULL) { - assign_type = (prop->key()->IsPropertyName()) - ? NAMED_PROPERTY - : KEYED_PROPERTY; - } + LhsKind assign_type = GetAssignType(prop); switch (assign_type) { case VARIABLE: { @@ -2457,6 +2449,42 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { CallStoreIC(); break; } + case NAMED_SUPER_PROPERTY: { + __ Push(rax); + VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); + EmitLoadHomeObject(prop->obj()->AsSuperReference()); + // stack: value, this; rax: home_object + Register scratch = rcx; + Register scratch2 = rdx; + __ Move(scratch, result_register()); // home_object + __ movp(rax, MemOperand(rsp, kPointerSize)); // value + __ movp(scratch2, MemOperand(rsp, 0)); // this + __ movp(MemOperand(rsp, kPointerSize), scratch2); // this + __ movp(MemOperand(rsp, 0), scratch); // home_object + // stack: this, home_object; rax: value + EmitNamedSuperPropertyStore(prop); + break; + } + case KEYED_SUPER_PROPERTY: { + __ Push(rax); + VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); + EmitLoadHomeObject(prop->obj()->AsSuperReference()); + __ Push(result_register()); + VisitForAccumulatorValue(prop->key()); + Register scratch = rcx; + Register scratch2 = rdx; + __ movp(scratch2, MemOperand(rsp, 2 * kPointerSize)); // value + // stack: value, this, home_object; rax: key, rdx: value + __ movp(scratch, MemOperand(rsp, kPointerSize)); // this + __ movp(MemOperand(rsp, 2 * kPointerSize), scratch); + __ movp(scratch, MemOperand(rsp, 0)); // home_object + __ movp(MemOperand(rsp, kPointerSize), scratch); + __ movp(MemOperand(rsp, 0), rax); + __ Move(rax, scratch2); + // stack: this, home_object, key; rax: value. + EmitKeyedSuperPropertyStore(prop); + break; + } case KEYED_PROPERTY: { __ Push(rax); // Preserve value. VisitForStackValue(prop->obj()); diff --git a/test/mjsunit/harmony/super.js b/test/mjsunit/harmony/super.js index cb13889..130c010 100644 --- a/test/mjsunit/harmony/super.js +++ b/test/mjsunit/harmony/super.js @@ -753,6 +753,66 @@ }()); +(function TestSetterInForIn() { + var setCalled = 0; + var getCalled = 0; + function Base() {} + Base.prototype = { + constructor: Base, + get x() { + getCalled++; + return 1; + }, + set x(v) { + setCalled++; + this.x_.push(v); + }, + }; + + function Derived() { + this.x_ = []; + } + Derived.prototype = { + __proto__: Base.prototype, + constructor: Derived, + }; + + Derived.prototype.testIter = function() { + setCalled = 0; + getCalled = 0; + for (super.x in [1,2,3]) {} + assertEquals(0, getCalled); + assertEquals(3, setCalled); + assertEquals(["0","1","2"], this.x_); + }.toMethod(Derived.prototype); + + new Derived().testIter(); + + var x = 'x'; + Derived.prototype.testIterKeyed = function() { + setCalled = 0; + getCalled = 0; + for (super[x] in [1,2,3]) {} + assertEquals(0, getCalled); + assertEquals(3, setCalled); + assertEquals(["0","1","2"], this.x_); + + this.x_ = []; + setCalled = 0; + getCalled = 0; + var toStringCalled = 0; + var o = {toString: function () { toStringCalled++; return x }}; + for (super[o] in [1,2,3]) {} + assertEquals(0, getCalled); + assertEquals(3, setCalled); + assertEquals(3, toStringCalled); + assertEquals(["0","1","2"], this.x_); + }.toMethod(Derived.prototype); + + new Derived().testIterKeyed(); +}()); + + (function TestKeyedSetterCreatingOwnProperties() { var ownReadOnly = 'ownReadOnly'; var ownReadonlyAccessor = 'ownReadonlyAccessor';