#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"
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.
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());
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());
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());
}
+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);
}
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