// If the function isn't compiled yet, the length is not computed
// correctly yet. Compile it now and return the right length.
HandleScope scope;
- Handle<JSFunction> function_handle(function);
- if (!CompileLazy(function_handle, KEEP_EXCEPTION)) {
+ Handle<SharedFunctionInfo> shared(function->shared());
+ if (!CompileLazyShared(shared, KEEP_EXCEPTION)) {
return Failure::Exception();
}
- return Smi::FromInt(function_handle->shared()->length());
+ return Smi::FromInt(shared->length());
} else {
return Smi::FromInt(function->shared()->length());
}
V8_Fatal(__FILE__, __LINE__, "Cannot resolve call to builtin %s", name);
}
#endif
- Handle<JSFunction> f = Handle<JSFunction>(JSFunction::cast(o));
+ Handle<SharedFunctionInfo> shared(JSFunction::cast(o)->shared());
// Make sure the number of parameters match the formal parameter count.
int argc = Bootstrapper::FixupFlagsArgumentsCount::decode(flags);
USE(argc);
- ASSERT(f->shared()->formal_parameter_count() == argc);
- if (!f->is_compiled()) {
- // Do lazy compilation and check for stack overflows.
- if (!CompileLazy(f, CLEAR_EXCEPTION)) {
- Clear();
- return false;
- }
+ ASSERT(shared->formal_parameter_count() == argc);
+ // Do lazy compilation if necessary and check for stack overflows.
+ if (!EnsureCompiled(shared, CLEAR_EXCEPTION)) {
+ Clear();
+ return false;
}
Code* code = Code::cast(code_[i]);
Address pc = code->instruction_start() + pc_[i];
RelocInfo target(pc, RelocInfo::CODE_TARGET, 0);
bool use_code_object = Bootstrapper::FixupFlagsUseCodeObject::decode(flags);
if (use_code_object) {
- target.set_target_object(f->code());
+ target.set_target_object(shared->code());
} else {
- target.set_target_address(f->code()->instruction_start());
+ target.set_target_address(shared->code()->instruction_start());
}
LOG(StringEvent("resolved", name));
}
if (Top::context() != NULL) {
Object* object = Top::builtins()->javascript_builtin(id);
if (object->IsJSFunction()) {
- Handle<JSFunction> function(JSFunction::cast(object));
+ Handle<SharedFunctionInfo> shared(JSFunction::cast(object)->shared());
// Make sure the number of parameters match the formal parameter count.
- ASSERT(function->shared()->formal_parameter_count() ==
+ ASSERT(shared->formal_parameter_count() ==
Builtins::GetArgumentsCount(id));
- if (function->is_compiled() || CompileLazy(function, CLEAR_EXCEPTION)) {
- code = function->code();
+ if (EnsureCompiled(shared, CLEAR_EXCEPTION)) {
+ code = shared->code();
*resolved = true;
}
}
Handle<Script> script,
Handle<Context> context,
bool is_eval,
- Handle<SharedFunctionInfo> shared) {
+ Handle<SharedFunctionInfo> shared,
+ Handle<Object> receiver) {
ASSERT(literal != NULL);
// Rewrite the AST by introducing .result assignments where needed.
}
} else if (FLAG_always_fast_compiler ||
(FLAG_fast_compiler && !is_run_once)) {
- FastCodeGenSyntaxChecker checker;
+ FastCodeGenSyntaxChecker checker(receiver);
checker.Check(literal);
if (checker.has_supported_syntax()) {
AstLabeler labeler;
HistogramTimerScope timer(rate);
// Compile the code.
- Handle<Code> code = MakeCode(lit, script, context, is_eval,
- Handle<SharedFunctionInfo>::null());
+ Handle<Code> code = MakeCode(lit,
+ script,
+ context,
+ is_eval,
+ Handle<SharedFunctionInfo>::null(),
+ Handle<Object>::null()); // No receiver.
// Check for stack-overflow exceptions.
if (code.is_null()) {
bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared,
+ Handle<Object> receiver,
int loop_nesting) {
CompilationZoneScope zone_scope(DELETE_ON_EXIT);
HistogramTimerScope timer(&Counters::compile_lazy);
// Compile the code.
- Handle<Code> code = MakeCode(lit, script, Handle<Context>::null(), false,
- shared);
+ Handle<Code> code = MakeCode(lit,
+ script,
+ Handle<Context>::null(),
+ false,
+ shared,
+ receiver);
// Check for stack-overflow exception.
if (code.is_null()) {
}
} else if (FLAG_always_fast_compiler ||
(FLAG_fast_compiler && !is_run_once)) {
- FastCodeGenSyntaxChecker checker;
+ // Since we are not lazily compiling we do not have a receiver to
+ // specialize for.
+ FastCodeGenSyntaxChecker checker(Handle<Object>::null());
checker.Check(literal);
if (checker.has_supported_syntax()) {
AstLabeler label_nodes;
// Compile from function info (used for lazy compilation). Returns
// true on success and false if the compilation resulted in a stack
// overflow.
- static bool CompileLazy(Handle<SharedFunctionInfo> shared, int loop_nesting);
+ static bool CompileLazy(Handle<SharedFunctionInfo> shared,
+ Handle<Object> receiver,
+ int loop_nesting);
// Compile a function boilerplate object (the function is possibly
// lazily compiled). Called recursively from a backend code
}
-bool Debug::EnsureCompiled(Handle<SharedFunctionInfo> shared) {
- if (shared->is_compiled()) return true;
- return CompileLazyShared(shared, CLEAR_EXCEPTION, 0);
-}
-
-
// Ensures the debug information is present for shared.
bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared) {
// Return if we already have the debug info for shared.
if (HasDebugInfo(shared)) return true;
// Ensure shared in compiled. Return false if this failed.
- if (!EnsureCompiled(shared)) return false;
+ if (!EnsureCompiled(shared, CLEAR_EXCEPTION)) return false;
// Create the debug info object.
Handle<DebugInfo> debug_info = Factory::NewDebugInfo(shared);
static void ClearStepOut();
static void ClearStepNext();
// Returns whether the compile succeeded.
- static bool EnsureCompiled(Handle<SharedFunctionInfo> shared);
static void RemoveDebugInfo(Handle<DebugInfo> debug_info);
static void SetAfterBreakTarget(JavaScriptFrame* frame);
static Handle<Object> CheckBreakPoints(Handle<Object> break_point);
void FastCodeGenSyntaxChecker::Check(FunctionLiteral* fun) {
- Scope* scope = fun->scope();
+ // We do not specialize if we do not have a receiver.
+ if (receiver().is_null()) BAILOUT("No receiver");
// We do not support stack or heap slots (both of which require
// allocation).
+ Scope* scope = fun->scope();
if (scope->num_stack_slots() > 0) {
BAILOUT("Function has stack-allocated locals");
}
BAILOUT("Non-named-property assignment");
}
+ // We will only specialize for fields on the object itself.
+ // Expression::IsPropertyName implies that the name is a literal
+ // symbol but we do not assume that.
+ Literal* key = prop->key()->AsLiteral();
+ if (key != NULL && key->handle()->IsString()) {
+ Handle<String> name = Handle<String>::cast(key->handle());
+ LookupResult lookup;
+ receiver()->Lookup(*name, &lookup);
+ if (lookup.holder() != *receiver()) BAILOUT("Non-own property assignment");
+ if (!lookup.type() == FIELD) BAILOUT("Non-field property assignment");
+ } else {
+ UNREACHABLE();
+ BAILOUT("Unexpected non-string-literal property key");
+ }
+
Visit(expr->value());
}
class FastCodeGenSyntaxChecker: public AstVisitor {
public:
- FastCodeGenSyntaxChecker() : has_supported_syntax_(true) {}
+ explicit FastCodeGenSyntaxChecker(Handle<Object> receiver)
+ : receiver_(receiver), has_supported_syntax_(true) {
+ }
void Check(FunctionLiteral* fun);
+ Handle<Object> receiver() { return receiver_; }
bool has_supported_syntax() { return has_supported_syntax_; }
private:
AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT
+ Handle<Object> receiver_;
bool has_supported_syntax_;
DISALLOW_COPY_AND_ASSIGN(FastCodeGenSyntaxChecker);
}
-bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
- ClearExceptionFlag flag,
- int loop_nesting) {
+bool EnsureCompiled(Handle<SharedFunctionInfo> shared,
+ ClearExceptionFlag flag) {
+ return shared->is_compiled() || CompileLazyShared(shared, flag);
+}
+
+
+static bool CompileLazyHelper(Handle<SharedFunctionInfo> shared,
+ Handle<Object> receiver,
+ ClearExceptionFlag flag,
+ int loop_nesting) {
// Compile the source information to a code object.
ASSERT(!shared->is_compiled());
- bool result = Compiler::CompileLazy(shared, loop_nesting);
+ bool result = Compiler::CompileLazy(shared, receiver, loop_nesting);
ASSERT(result != Top::has_pending_exception());
if (!result && flag == CLEAR_EXCEPTION) Top::clear_pending_exception();
return result;
}
-bool CompileLazy(Handle<JSFunction> function, ClearExceptionFlag flag) {
+bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
+ ClearExceptionFlag flag) {
+ return CompileLazyHelper(shared, Handle<Object>::null(), flag, 0);
+}
+
+
+bool CompileLazy(Handle<JSFunction> function,
+ Handle<Object> receiver,
+ ClearExceptionFlag flag) {
// Compile the source information to a code object.
Handle<SharedFunctionInfo> shared(function->shared());
- bool result = CompileLazyShared(shared, flag, 0);
+ bool result = CompileLazyHelper(shared, receiver, flag, 0);
LOG(FunctionCreateEvent(*function));
return result;
}
-bool CompileLazyInLoop(Handle<JSFunction> function, ClearExceptionFlag flag) {
+bool CompileLazyInLoop(Handle<JSFunction> function,
+ Handle<Object> receiver,
+ ClearExceptionFlag flag) {
// Compile the source information to a code object.
Handle<SharedFunctionInfo> shared(function->shared());
- bool result = CompileLazyShared(shared, flag, 1);
+ bool result = CompileLazyHelper(shared, receiver, flag, 1);
LOG(FunctionCreateEvent(*function));
return result;
}
+
OptimizedObjectForAddingMultipleProperties::
OptimizedObjectForAddingMultipleProperties(Handle<JSObject> object,
int expected_additional_properties,
// false if the compilation resulted in a stack overflow.
enum ClearExceptionFlag { KEEP_EXCEPTION, CLEAR_EXCEPTION };
+bool EnsureCompiled(Handle<SharedFunctionInfo> shared,
+ ClearExceptionFlag flag);
+
bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
- ClearExceptionFlag flag,
- int loop_nesting);
+ ClearExceptionFlag flag);
+
+bool CompileLazy(Handle<JSFunction> function,
+ Handle<Object> receiver,
+ ClearExceptionFlag flag);
-bool CompileLazy(Handle<JSFunction> function, ClearExceptionFlag flag);
-bool CompileLazyInLoop(Handle<JSFunction> function, ClearExceptionFlag flag);
+bool CompileLazyInLoop(Handle<JSFunction> function,
+ Handle<Object> receiver,
+ ClearExceptionFlag flag);
// Returns the lazy compilation stub for argc arguments.
Handle<Code> ComputeLazyCompile(int argc);
Handle<JSFunction> function = Handle<JSFunction>(JSFunction::cast(result));
InLoopFlag in_loop = ic.target()->ic_in_loop();
if (in_loop == IN_LOOP) {
- CompileLazyInLoop(function, CLEAR_EXCEPTION);
+ CompileLazyInLoop(function, args.at<Object>(0), CLEAR_EXCEPTION);
} else {
- CompileLazy(function, CLEAR_EXCEPTION);
+ CompileLazy(function, args.at<Object>(0), CLEAR_EXCEPTION);
}
return *function;
}
if (!code->IsNull()) {
RUNTIME_ASSERT(code->IsJSFunction());
Handle<JSFunction> fun = Handle<JSFunction>::cast(code);
- SetExpectedNofProperties(target, fun->shared()->expected_nof_properties());
- if (!fun->is_compiled() && !CompileLazy(fun, KEEP_EXCEPTION)) {
+ Handle<SharedFunctionInfo> shared(fun->shared());
+ SetExpectedNofProperties(target, shared->expected_nof_properties());
+
+ if (!EnsureCompiled(shared, KEEP_EXCEPTION)) {
return Failure::Exception();
}
// Set the code, formal parameter count, and the length of the target
// function.
target->set_code(fun->code());
- target->shared()->set_length(fun->shared()->length());
+ target->shared()->set_length(shared->length());
target->shared()->set_formal_parameter_count(
- fun->shared()->formal_parameter_count());
+ shared->formal_parameter_count());
// Set the source code of the target function to undefined.
// SetCode is only used for built-in constructors like String,
// Array, and Object, and some web code
}
// The function should be compiled for the optimization hints to be available.
- if (!function->shared()->is_compiled()) {
- CompileLazyShared(Handle<SharedFunctionInfo>(function->shared()),
- CLEAR_EXCEPTION,
- 0);
- LOG(FunctionCreateEvent(*function));
- }
+ Handle<SharedFunctionInfo> shared(function->shared());
+ EnsureCompiled(shared, CLEAR_EXCEPTION);
bool first_allocation = !function->has_initial_map();
Handle<JSObject> result = Factory::NewJSObject(function);
// this means that things called through constructors are never known to
// be in loops. We compile them as if they are in loops here just in case.
ASSERT(!function->is_compiled());
- if (!CompileLazyInLoop(function, KEEP_EXCEPTION)) {
+ if (!CompileLazyInLoop(function, Handle<Object>::null(), KEEP_EXCEPTION)) {
return Failure::Exception();
}
if (!done) {
// If the candidate is not compiled compile it to reveal any inner
// functions which might contain the requested source position.
- CompileLazyShared(target, KEEP_EXCEPTION, 0);
+ CompileLazyShared(target, KEEP_EXCEPTION);
}
}
ASSERT(args.length() == 1);
// Get the function and make sure it is compiled.
CONVERT_ARG_CHECKED(JSFunction, func, 0);
- if (!func->is_compiled() && !CompileLazy(func, KEEP_EXCEPTION)) {
+ Handle<SharedFunctionInfo> shared(func->shared());
+ if (!EnsureCompiled(shared, KEEP_EXCEPTION)) {
return Failure::Exception();
}
func->code()->PrintLn();
ASSERT(args.length() == 1);
// Get the function and make sure it is compiled.
CONVERT_ARG_CHECKED(JSFunction, func, 0);
- if (!func->is_compiled() && !CompileLazy(func, KEEP_EXCEPTION)) {
+ Handle<SharedFunctionInfo> shared(func->shared());
+ if (!EnsureCompiled(shared, KEEP_EXCEPTION)) {
return Failure::Exception();
}
- func->shared()->construct_stub()->PrintLn();
+ shared->construct_stub()->PrintLn();
#endif // DEBUG
return Heap::undefined_value();
}