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:
parent
22d5ceb1f2
commit
dd3c097123
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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(); }
|
||||
|
@ -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_;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user