Reviewers: wingo,

Description:
WIP context-allocation for "this" in arrow functions

BUG=

Please review this at https://codereview.chromium.org/791603003/

Base URL: https://chromium.googlesource.com/v8/v8.git@master

Affected files (+61, -4 lines):
  M src/heap/heap.h
  M src/scopes.cc
  M src/x64/full-codegen-x64.cc


Index: src/heap/heap.h
diff --git a/src/heap/heap.h b/src/heap/heap.h
index 69e232b043cbfe62957713ae059aadf9b6bbea2c..a0906f8fbb0dfafa32409faa85e86bde4f127dcc 100644
--- a/src/heap/heap.h
+++ b/src/heap/heap.h
@@ -276,7 +276,8 @@ namespace internal {
   V(minus_zero_string, "-0")                               \
   V(Array_string, "Array")                                 \
   V(Error_string, "Error")                                 \
-  V(RegExp_string, "RegExp")
+  V(RegExp_string, "RegExp")                               \
+  V(this_string, "this")

 #define PRIVATE_SYMBOL_LIST(V)      \
   V(frozen_symbol)                  \
Index: src/scopes.cc
diff --git a/src/scopes.cc b/src/scopes.cc
index 39b67a886444fe1db46a54e4006d37abd68d447a..7aba5b5c283ae4c1bd97083d62fedfef40c3ceb4 100644
--- a/src/scopes.cc
+++ b/src/scopes.cc
@@ -609,6 +609,13 @@ void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals,
     }
   }

+  // Collect "this", if marked for context allocation.
+  // XXX: Is this correct?
+  if (receiver_ && receiver_->has_forced_context_allocation()) {
+       DCHECK(receiver_->IsContextSlot()); // uh?
+       context_locals->Add(receiver_, zone());
+       }
+
// Collect temporaries which are always allocated on the stack, unless the
   // context as a whole has forced context allocation.
   for (int i = 0; i < temps_.length(); i++) {
@@ -1324,6 +1331,24 @@ void Scope::AllocateParameterLocals() {
       }
     }
   }
+
+  // For arrow functions, we must force context allocation of the
+  // this/super/arguments from the outer scope, if they are used.
+  if (is_arrow_scope()) {
+    if (scope_uses_this_ || inner_scope_uses_this_) {
+      if (outer_scope_) {
+        DCHECK(outer_scope_->receiver_);
+        Variable* var = outer_scope_->receiver_;
+        var->ForceContextAllocation();
+
+                               DCHECK(MustAllocateInContext(var));
+                               AllocateHeapSlot(var);
+      }
+    }
+    if (scope_uses_arguments_ || inner_scope_uses_arguments_) {
+      // TODO(aperez): Implement.
+    }
+  }
 }


Index: src/x64/full-codegen-x64.cc
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index 24747ee9e85b11d7e3fed1b50e70db0d2073e9b2..cd0e305b40417225fd0379c5850dc7f46608a697 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -113,8 +113,11 @@ void FullCodeGenerator::Generate() {

// Sloppy mode functions and builtins need to replace the receiver with the
   // global proxy when called as functions (without an explicit receiver
-  // object).
-  if (info->strict_mode() == SLOPPY && !info->is_native()) {
+ // object). Arrow functions need to replace the receiver with the receiver
+  // of the parent scope.
+
+  if (info->strict_mode() == SLOPPY && !info->is_native() &&
+      !info->function()->is_arrow()) {
     Label ok;
     // +1 for return address.
     StackArgumentsAccessor args(rsp, info->scope()->num_parameters());
@@ -232,6 +235,33 @@ void FullCodeGenerator::Generate() {
     }
   }

+  // For arrow functions, patch up the receiver
+  if (info->function()->is_arrow()) {
+    Scope* scope = info->scope();
+    DCHECK(scope->scope_type() == ARROW_SCOPE);
+
+    // The value of the receiver must be patched up after the context
+    // object, in case the "this" variable is in the context.
+    if (scope->uses_this() || scope->inner_uses_this()) {
+      Comment cmnt(masm_, "[ Patch up receiver for arrow function");
+
+      Label ok;
+      StackArgumentsAccessor args(rsp, scope->num_parameters());
+
+      __ Push(rsi);  // Context
+      __ Push(isolate()->factory()->this_string());
+      __ CallRuntime(Runtime::kLoadLookupSlot, 2);
+
+      __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
+      __ j(not_equal, &ok, Label::kNear);
+      __ Push(isolate()->factory()->this_string());
+      __ CallRuntime(Runtime::kThrowReferenceError, 1);
+
+      __ bind(&ok);
+      __ movp(args.GetReceiverOperand(), rax);
+    }
+  }
+
   // Possibly allocate an arguments object.
   Variable* arguments = scope()->arguments();
   if (arguments != NULL) {
@@ -2721,7 +2751,8 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
       PrepareForBailout(callee, NO_REGISTERS);
     }
// Push undefined as receiver. This is patched in the method prologue if it
-    // is a sloppy mode method.
+    // is a sloppy mode method, or by the function prologue it is an arrow
+    // function.
     __ Push(isolate()->factory()->undefined_value());
   } else {
     // Load the function from the receiver.


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to