Load global object and builtins from activation.
authorsigurds@chromium.org <sigurds@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 19 Aug 2014 15:16:23 +0000 (15:16 +0000)
committersigurds@chromium.org <sigurds@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 19 Aug 2014 15:16:23 +0000 (15:16 +0000)
BUG=
R=titzer@chromium.org

Review URL: https://codereview.chromium.org/474633003

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23205 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/compiler/ast-graph-builder.cc
src/compiler/ast-graph-builder.h
test/cctest/compiler/test-run-jscalls.cc

index e7e8828..7726dc7 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "src/compiler.h"
 #include "src/compiler/control-builders.h"
+#include "src/compiler/machine-operator.h"
 #include "src/compiler/node-properties.h"
 #include "src/compiler/node-properties-inl.h"
 #include "src/full-codegen.h"
@@ -737,13 +738,12 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
           test_should_filter.If(should_filter_cond);
           test_should_filter.Then();
           value = environment()->Pop();
-          // TODO(dcarney): Better load from function context.
-          // See comment in BuildLoadBuiltinsObject.
-          Handle<JSFunction> function(JSFunction::cast(
-              info()->context()->builtins()->javascript_builtin(
-                  Builtins::FILTER_KEY)));
+          Node* builtins = BuildLoadBuiltinsObject();
+          Node* function = BuildLoadObjectField(
+              builtins,
+              JSBuiltinsObject::OffsetOfFunctionWithId(Builtins::FILTER_KEY));
           // Callee.
-          environment()->Push(jsgraph()->HeapConstant(function));
+          environment()->Push(function);
           // Receiver.
           environment()->Push(obj);
           // Args.
@@ -875,10 +875,11 @@ void AstGraphBuilder::VisitLiteral(Literal* expr) {
 
 
 void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
-  Handle<JSFunction> closure = info()->closure();
+  Node* closure = GetFunctionClosure();
 
   // Create node to materialize a regular expression literal.
-  Node* literals_array = jsgraph()->Constant(handle(closure->literals()));
+  Node* literals_array =
+      BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
   Node* literal_index = jsgraph()->Constant(expr->literal_index());
   Node* pattern = jsgraph()->Constant(expr->pattern());
   Node* flags = jsgraph()->Constant(expr->flags());
@@ -889,11 +890,12 @@ void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
 
 
 void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
-  Handle<JSFunction> closure = info()->closure();
+  Node* closure = GetFunctionClosure();
 
   // Create node to deep-copy the literal boilerplate.
   expr->BuildConstantProperties(isolate());
-  Node* literals_array = jsgraph()->Constant(handle(closure->literals()));
+  Node* literals_array =
+      BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
   Node* literal_index = jsgraph()->Constant(expr->literal_index());
   Node* constants = jsgraph()->Constant(expr->constant_properties());
   Node* flags = jsgraph()->Constant(expr->ComputeFlags());
@@ -998,11 +1000,12 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
 
 
 void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
-  Handle<JSFunction> closure = info()->closure();
+  Node* closure = GetFunctionClosure();
 
   // Create node to deep-copy the literal boilerplate.
   expr->BuildConstantElements(isolate());
-  Node* literals_array = jsgraph()->Constant(handle(closure->literals()));
+  Node* literals_array =
+      BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
   Node* literal_index = jsgraph()->Constant(expr->literal_index());
   Node* constants = jsgraph()->Constant(expr->constant_elements());
   Node* flags = jsgraph()->Constant(expr->ComputeFlags());
@@ -1938,25 +1941,28 @@ Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value,
 }
 
 
+Node* AstGraphBuilder::BuildLoadObjectField(Node* object, int offset) {
+  // TODO(sigurds) Use simplified load here once it is ready.
+  MachineOperatorBuilder machine(zone());
+  Node* field_load = NewNode(machine.Load(kMachAnyTagged), object,
+                             jsgraph_->Int32Constant(offset - kHeapObjectTag));
+  return field_load;
+}
+
+
 Node* AstGraphBuilder::BuildLoadBuiltinsObject() {
-  // TODO(mstarzinger): Better load from function context, otherwise optimized
-  // code cannot be shared across native contexts.
-  return jsgraph()->Constant(handle(info()->context()->builtins()));
+  Node* global = BuildLoadGlobalObject();
+  Node* builtins =
+      BuildLoadObjectField(global, JSGlobalObject::kBuiltinsOffset);
+  return builtins;
 }
 
 
 Node* AstGraphBuilder::BuildLoadGlobalObject() {
-#if 0
   Node* context = GetFunctionContext();
-  // TODO(mstarzinger): Use mid-level operator on FixedArray instead of the
-  // JS-level operator that targets JSObject.
-  Node* index = jsgraph()->Constant(Context::GLOBAL_OBJECT_INDEX);
-  return NewNode(javascript()->LoadProperty(), context, index);
-#else
-  // TODO(mstarzinger): Better load from function context, otherwise optimized
-  // code cannot be shared across native contexts. See unused code above.
-  return jsgraph()->Constant(handle(info()->context()->global_object()));
-#endif
+  Operator* load_op =
+      javascript()->LoadContext(0, Context::GLOBAL_OBJECT_INDEX, true);
+  return NewNode(load_op, context);
 }
 
 
index 861bd5b..a5823c0 100644 (file)
@@ -88,6 +88,7 @@ class AstGraphBuilder : public StructuredGraphBuilder, public AstVisitor {
   Node* BuildLoadBuiltinsObject();
   Node* BuildLoadGlobalObject();
   Node* BuildLoadClosure();
+  Node* BuildLoadObjectField(Node* object, int offset);
 
   // Builders for automatic type conversion.
   Node* BuildToBoolean(Node* value);
index fa7e98d..a29bde3 100644 (file)
@@ -245,3 +245,88 @@ TEST(CallEval) {
 
   T.CheckCall(T.Val(42), T.Val("x"), T.undefined());
 }
+
+#if V8_TURBOFAN_TARGET
+
+TEST(ContextLoadedFromActivation) {
+  i::FLAG_turbo_filter = "*";
+  i::FLAG_always_opt = true;
+  i::FLAG_context_specialization = false;
+
+  const char* script =
+      "var x = 42;"
+      "(function() {"
+      "  return function () { return x };"
+      "})()";
+
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope outer(isolate);
+  v8::Local<v8::Value> fun;
+  {
+    v8::Local<v8::Context> env = v8::Context::New(isolate);
+    env->Enter();
+    CompileRun("var x = 42;");
+    fun = CompileRun(script);
+    env->Global()->Set(v8_str("foo"), fun);
+    ExpectInt32("foo();", 42);
+    env->Exit();
+  }
+
+  {
+    v8::Local<v8::Context> env = v8::Context::New(isolate);
+    env->Enter();
+    v8::Local<v8::Value> fun2 = CompileRun(script);
+    i::Handle<i::Object> oifun = v8::Utils::OpenHandle(*fun);
+    i::Handle<i::JSFunction> ifun = Handle<JSFunction>::cast(oifun);
+    i::Handle<i::Object> oifun2 = v8::Utils::OpenHandle(*fun2);
+    i::Handle<i::JSFunction> ifun2 = Handle<JSFunction>::cast(oifun2);
+    ifun2->set_code(ifun->code());
+    env->Global()->Set(v8_str("foo"), fun2);
+    CompileRun("var x = 24;");
+    ExpectInt32("foo();", 24);
+    env->Exit();
+  }
+}
+
+
+TEST(BuiltinLoadedFromActivation) {
+  i::FLAG_turbo_filter = "*";
+  i::FLAG_always_opt = true;
+  i::FLAG_context_specialization = false;
+
+  const char* script =
+      "var x = 42;"
+      "(function() {"
+      "  return function () { return this; };"
+      "})()";
+
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope outer(isolate);
+  v8::Local<v8::Value> fun;
+  {
+    v8::Local<v8::Context> env = v8::Context::New(isolate);
+    env->Enter();
+    CompileRun("var x = 42;");
+    fun = CompileRun(script);
+    env->Global()->Set(v8_str("foo"), fun);
+    ExpectObject("foo()", env->Global());
+    env->Exit();
+  }
+
+  {
+    v8::Local<v8::Context> env = v8::Context::New(isolate);
+    env->Enter();
+    v8::Local<v8::Value> fun2 = CompileRun(script);
+    i::Handle<i::Object> oifun = v8::Utils::OpenHandle(*fun);
+    i::Handle<i::JSFunction> ifun = Handle<JSFunction>::cast(oifun);
+    i::Handle<i::Object> oifun2 = v8::Utils::OpenHandle(*fun2);
+    i::Handle<i::JSFunction> ifun2 = Handle<JSFunction>::cast(oifun2);
+    ifun2->set_code(ifun->code());
+    env->Global()->Set(v8_str("foo"), fun2);
+    CompileRun("var x = 24;");
+    ExpectObject("foo()", env->Global());
+    env->Exit();
+  }
+}
+
+#endif  // V8_TURBO_TARGET