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.