Reland "Load global object and builtins from activation."

Reland fixes:
Don't set string flags (doing so leaks memory).

Load closure from activation for building literals.

R=titzer@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23275 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
sigurds@chromium.org 2014-08-21 12:40:10 +00:00
parent 22d5ceb1f2
commit dd3c097123
6 changed files with 91 additions and 29 deletions

View 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"
@ -701,13 +702,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.
@ -840,10 +840,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());
@ -854,11 +855,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());
@ -963,11 +965,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());
@ -1908,25 +1911,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);
}

View 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);

View File

@ -186,7 +186,7 @@ Handle<Code> Pipeline::GenerateCode() {
VerifyAndPrintGraph(&graph, "Initial untyped");
if (FLAG_context_specialization) {
if (context_specialization_) {
SourcePositionTable::Scope pos(&source_positions,
SourcePosition::Unknown());
// Specialize the code to the context as aggressively as possible.

View File

@ -24,7 +24,8 @@ class Linkage;
class Pipeline {
public:
explicit Pipeline(CompilationInfo* info) : info_(info) {}
explicit Pipeline(CompilationInfo* info)
: info_(info), context_specialization_(FLAG_context_specialization) {}
// Run the entire pipeline and generate a handle to a code object.
Handle<Code> GenerateCode();
@ -39,9 +40,14 @@ class Pipeline {
static void SetUp();
static void TearDown();
bool context_specialization() { return context_specialization_; }
void set_context_specialization(bool context_specialization) {
context_specialization_ = context_specialization;
}
private:
CompilationInfo* info_;
bool context_specialization_;
CompilationInfo* info() const { return info_; }
Isolate* isolate() { return info_->isolate(); }

View File

@ -26,10 +26,13 @@ namespace compiler {
class FunctionTester : public InitializedHandleScope {
public:
explicit FunctionTester(const char* source)
explicit FunctionTester(const char* source, bool context_specialization =
FLAG_context_specialization)
: isolate(main_isolate()),
function((FLAG_allow_natives_syntax = true, NewFunction(source))) {
function((FLAG_allow_natives_syntax = true, NewFunction(source))),
context_specialization_(context_specialization) {
Compile(function);
USE(context_specialization_);
}
Isolate* isolate;
@ -52,6 +55,7 @@ class FunctionTester : public InitializedHandleScope {
EnsureDeoptimizationSupport(&info);
Pipeline pipeline(&info);
pipeline.set_context_specialization(context_specialization_);
Handle<Code> code = pipeline.GenerateCode();
CHECK(!code.is_null());
@ -188,6 +192,9 @@ class FunctionTester : public InitializedHandleScope {
Handle<Object> true_value() { return isolate->factory()->true_value(); }
Handle<Object> false_value() { return isolate->factory()->false_value(); }
private:
bool context_specialization_;
};
}
}

View File

@ -245,3 +245,45 @@ TEST(CallEval) {
T.CheckCall(T.Val(42), T.Val("x"), T.undefined());
}
TEST(ContextLoadedFromActivation) {
const char* script =
"var x = 42;"
"(function() {"
" return function () { return x };"
"})()";
// Disable context specialization.
FunctionTester T(script, false);
v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
v8::Context::Scope scope(context);
v8::Local<v8::Value> value = CompileRun(script);
i::Handle<i::Object> ofun = v8::Utils::OpenHandle(*value);
i::Handle<i::JSFunction> jsfun = Handle<JSFunction>::cast(ofun);
jsfun->set_code(T.function->code());
context->Global()->Set(v8_str("foo"), v8::Utils::ToLocal(jsfun));
CompileRun("var x = 24;");
ExpectInt32("foo();", 24);
}
TEST(BuiltinLoadedFromActivation) {
const char* script =
"var x = 42;"
"(function() {"
" return function () { return this; };"
"})()";
// Disable context specialization.
FunctionTester T(script, false);
v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
v8::Context::Scope scope(context);
v8::Local<v8::Value> value = CompileRun(script);
i::Handle<i::Object> ofun = v8::Utils::OpenHandle(*value);
i::Handle<i::JSFunction> jsfun = Handle<JSFunction>::cast(ofun);
jsfun->set_code(T.function->code());
context->Global()->Set(v8_str("foo"), v8::Utils::ToLocal(jsfun));
CompileRun("var x = 24;");
ExpectObject("foo()", context->Global());
}