Commit 371ad73a authored by yangguo's avatar yangguo Committed by Commit bot

Do not use js builtins object to determine whether a function is a builtin.

We can use the script type to determine that instead. Script of type
TYPE_NATIVE are considered builtins, TYPE_NORMAL are not. The only exception
to this rule is the empty function, for which the script is TYPE_NATIVE
(observable by the debugger), but should be stringified to "function () {}"
instead of "function () { [native code] }". For this, I introduce a
hide_source flag on the script object.

We also use IsBuiltin and IsSubjectToDebugging interchangeably. For debugger,
we now use the latter, hiding the detail that only non-builtins are debuggable.

R=mstarzinger@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#30285}
parent cd351559
...@@ -1361,6 +1361,7 @@ Handle<SharedFunctionInfo> Compiler::CompileScript( ...@@ -1361,6 +1361,7 @@ Handle<SharedFunctionInfo> Compiler::CompileScript(
Handle<Script> script = isolate->factory()->NewScript(source); Handle<Script> script = isolate->factory()->NewScript(source);
if (natives == NATIVES_CODE) { if (natives == NATIVES_CODE) {
script->set_type(Smi::FromInt(Script::TYPE_NATIVE)); script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
script->set_hide_source(true);
} }
if (!script_name.is_null()) { if (!script_name.is_null()) {
script->set_name(*script_name); script->set_name(*script_name);
......
...@@ -118,7 +118,7 @@ ScopeIterator::ScopeIterator(Isolate* isolate, Handle<JSFunction> function) ...@@ -118,7 +118,7 @@ ScopeIterator::ScopeIterator(Isolate* isolate, Handle<JSFunction> function)
context_(function->context()), context_(function->context()),
seen_script_scope_(false), seen_script_scope_(false),
failed_(false) { failed_(false) {
if (function->IsBuiltin()) context_ = Handle<Context>(); if (!function->IsSubjectToDebugging()) context_ = Handle<Context>();
} }
......
...@@ -2277,7 +2277,7 @@ void Debug::HandleDebugBreak() { ...@@ -2277,7 +2277,7 @@ void Debug::HandleDebugBreak() {
Object* fun = it.frame()->function(); Object* fun = it.frame()->function();
if (fun && fun->IsJSFunction()) { if (fun && fun->IsJSFunction()) {
// Don't stop in builtin functions. // Don't stop in builtin functions.
if (JSFunction::cast(fun)->IsBuiltin()) return; if (!JSFunction::cast(fun)->IsSubjectToDebugging()) return;
GlobalObject* global = JSFunction::cast(fun)->context()->global_object(); GlobalObject* global = JSFunction::cast(fun)->context()->global_object();
// Don't stop in debugger functions. // Don't stop in debugger functions.
if (IsDebugGlobal(global)) return; if (IsDebugGlobal(global)) return;
......
...@@ -313,18 +313,13 @@ static bool IsVisibleInStackTrace(JSFunction* fun, ...@@ -313,18 +313,13 @@ static bool IsVisibleInStackTrace(JSFunction* fun,
} }
// Skip all frames until we've seen the caller. // Skip all frames until we've seen the caller.
if (!(*seen_caller)) return false; if (!(*seen_caller)) return false;
// Also, skip non-visible built-in functions and any call with the builtins // Functions defined in native scripts are not visible unless directly
// object as receiver, so as to not reveal either the builtins object or // exposed, in which case the native flag is set.
// an internal function.
// The --builtins-in-stack-traces command line flag allows including // The --builtins-in-stack-traces command line flag allows including
// internal call sites in the stack trace for debugging purposes. // internal call sites in the stack trace for debugging purposes.
if (!FLAG_builtins_in_stack_traces) { if (!FLAG_builtins_in_stack_traces) {
if (receiver->IsJSBuiltinsObject()) return false; if (receiver->IsJSBuiltinsObject()) return false;
if (fun->IsBuiltin()) { if (fun->IsBuiltin()) return fun->shared()->native();
return fun->shared()->native();
} else if (!fun->IsSubjectToDebugging()) {
return false;
}
} }
return true; return true;
} }
......
...@@ -5552,6 +5552,10 @@ void Script::set_compilation_type(CompilationType type) { ...@@ -5552,6 +5552,10 @@ void Script::set_compilation_type(CompilationType type) {
set_flags(BooleanBit::set(flags(), kCompilationTypeBit, set_flags(BooleanBit::set(flags(), kCompilationTypeBit,
type == COMPILATION_TYPE_EVAL)); type == COMPILATION_TYPE_EVAL));
} }
bool Script::hide_source() { return BooleanBit::get(flags(), kHideSourceBit); }
void Script::set_hide_source(bool value) {
set_flags(BooleanBit::set(flags(), kHideSourceBit, value));
}
Script::CompilationState Script::compilation_state() { Script::CompilationState Script::compilation_state() {
return BooleanBit::get(flags(), kCompilationStateBit) ? return BooleanBit::get(flags(), kCompilationStateBit) ?
COMPILATION_STATE_COMPILED : COMPILATION_STATE_INITIAL; COMPILATION_STATE_COMPILED : COMPILATION_STATE_INITIAL;
...@@ -6017,18 +6021,19 @@ void SharedFunctionInfo::set_disable_optimization_reason(BailoutReason reason) { ...@@ -6017,18 +6021,19 @@ void SharedFunctionInfo::set_disable_optimization_reason(BailoutReason reason) {
} }
bool SharedFunctionInfo::IsSubjectToDebugging() { bool SharedFunctionInfo::IsBuiltin() {
Object* script_obj = script(); Object* script_obj = script();
if (script_obj->IsUndefined()) return false; if (script_obj->IsUndefined()) return true;
Script* script = Script::cast(script_obj); Script* script = Script::cast(script_obj);
Script::Type type = static_cast<Script::Type>(script->type()->value()); Script::Type type = static_cast<Script::Type>(script->type()->value());
return type == Script::TYPE_NORMAL; return type != Script::TYPE_NORMAL;
} }
bool JSFunction::IsBuiltin() { bool SharedFunctionInfo::IsSubjectToDebugging() { return !IsBuiltin(); }
return context()->global_object()->IsJSBuiltinsObject();
}
bool JSFunction::IsBuiltin() { return shared()->IsBuiltin(); }
bool JSFunction::IsSubjectToDebugging() { bool JSFunction::IsSubjectToDebugging() {
......
...@@ -5916,6 +5916,11 @@ class Script: public Struct { ...@@ -5916,6 +5916,11 @@ class Script: public Struct {
inline CompilationState compilation_state(); inline CompilationState compilation_state();
inline void set_compilation_state(CompilationState state); inline void set_compilation_state(CompilationState state);
// [hide_source]: determines whether the script source can be exposed as
// function source. Encoded in the 'flags' field.
inline bool hide_source();
inline void set_hide_source(bool value);
// [origin_options]: optional attributes set by the embedder via ScriptOrigin, // [origin_options]: optional attributes set by the embedder via ScriptOrigin,
// and used by the embedder to make decisions about the script. V8 just passes // and used by the embedder to make decisions about the script. V8 just passes
// this through. Encoded in the 'flags' field. // this through. Encoded in the 'flags' field.
...@@ -5988,7 +5993,8 @@ class Script: public Struct { ...@@ -5988,7 +5993,8 @@ class Script: public Struct {
// Bit positions in the flags field. // Bit positions in the flags field.
static const int kCompilationTypeBit = 0; static const int kCompilationTypeBit = 0;
static const int kCompilationStateBit = 1; static const int kCompilationStateBit = 1;
static const int kOriginOptionsShift = 2; static const int kHideSourceBit = 2;
static const int kOriginOptionsShift = 3;
static const int kOriginOptionsSize = 3; static const int kOriginOptionsSize = 3;
static const int kOriginOptionsMask = ((1 << kOriginOptionsSize) - 1) static const int kOriginOptionsMask = ((1 << kOriginOptionsSize) - 1)
<< kOriginOptionsShift; << kOriginOptionsShift;
...@@ -6398,6 +6404,9 @@ class SharedFunctionInfo: public HeapObject { ...@@ -6398,6 +6404,9 @@ class SharedFunctionInfo: public HeapObject {
// Tells whether this function should be subject to debugging. // Tells whether this function should be subject to debugging.
inline bool IsSubjectToDebugging(); inline bool IsSubjectToDebugging();
// Whether this function is defined in native code or extensions.
inline bool IsBuiltin();
// Check whether or not this function is inlineable. // Check whether or not this function is inlineable.
bool IsInlineable(); bool IsInlineable();
......
...@@ -533,6 +533,7 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) { ...@@ -533,6 +533,7 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
// Get scope info and read from it for local variable information. // Get scope info and read from it for local variable information.
Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction())); Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
RUNTIME_ASSERT(function->IsSubjectToDebugging());
Handle<SharedFunctionInfo> shared(function->shared()); Handle<SharedFunctionInfo> shared(function->shared());
Handle<ScopeInfo> scope_info(shared->scope_info()); Handle<ScopeInfo> scope_info(shared->scope_info());
DCHECK(*scope_info != ScopeInfo::Empty(isolate)); DCHECK(*scope_info != ScopeInfo::Empty(isolate));
...@@ -712,8 +713,8 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) { ...@@ -712,8 +713,8 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
// THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
// THE FRAME ITERATOR TO WRAP THE RECEIVER. // THE FRAME ITERATOR TO WRAP THE RECEIVER.
Handle<Object> receiver(it.frame()->receiver(), isolate); Handle<Object> receiver(it.frame()->receiver(), isolate);
if (!receiver->IsJSObject() && is_sloppy(shared->language_mode()) && DCHECK(!function->IsBuiltin());
!function->IsBuiltin()) { if (!receiver->IsJSObject() && is_sloppy(shared->language_mode())) {
// If the receiver is not a JSObject and the function is not a // If the receiver is not a JSObject and the function is not a
// builtin or strict-mode we have hit an optimization where a // builtin or strict-mode we have hit an optimization where a
// value object is not converted into a wrapped JS objects. To // value object is not converted into a wrapped JS objects. To
...@@ -1634,7 +1635,7 @@ RUNTIME_FUNCTION(Runtime_DebugCallbackSupportsStepping) { ...@@ -1634,7 +1635,7 @@ RUNTIME_FUNCTION(Runtime_DebugCallbackSupportsStepping) {
// or not even a function. // or not even a function.
return isolate->heap()->ToBoolean( return isolate->heap()->ToBoolean(
callback->IsJSFunction() && callback->IsJSFunction() &&
(!JSFunction::cast(callback)->IsBuiltin() || (JSFunction::cast(callback)->IsSubjectToDebugging() ||
JSFunction::cast(callback)->shared()->bound())); JSFunction::cast(callback)->shared()->bound()));
} }
......
...@@ -192,12 +192,15 @@ RUNTIME_FUNCTION(Runtime_FunctionIsAPIFunction) { ...@@ -192,12 +192,15 @@ RUNTIME_FUNCTION(Runtime_FunctionIsAPIFunction) {
} }
RUNTIME_FUNCTION(Runtime_FunctionIsBuiltin) { RUNTIME_FUNCTION(Runtime_FunctionHidesSource) {
SealHandleScope shs(isolate); SealHandleScope shs(isolate);
DCHECK(args.length() == 1); DCHECK(args.length() == 1);
CONVERT_ARG_CHECKED(JSFunction, f, 0); CONVERT_ARG_CHECKED(JSFunction, f, 0);
return isolate->heap()->ToBoolean(f->IsBuiltin());
SharedFunctionInfo* shared = f->shared();
bool hide_source = !shared->script()->IsScript() ||
Script::cast(shared->script())->hide_source();
return isolate->heap()->ToBoolean(hide_source);
} }
......
...@@ -236,7 +236,7 @@ namespace internal { ...@@ -236,7 +236,7 @@ namespace internal {
F(FunctionSetLength, 2, 1) \ F(FunctionSetLength, 2, 1) \
F(FunctionSetPrototype, 2, 1) \ F(FunctionSetPrototype, 2, 1) \
F(FunctionIsAPIFunction, 1, 1) \ F(FunctionIsAPIFunction, 1, 1) \
F(FunctionIsBuiltin, 1, 1) \ F(FunctionHidesSource, 1, 1) \
F(SetCode, 2, 1) \ F(SetCode, 2, 1) \
F(SetNativeFlag, 1, 1) \ F(SetNativeFlag, 1, 1) \
F(ThrowStrongModeTooFewArguments, 0, 1) \ F(ThrowStrongModeTooFewArguments, 0, 1) \
......
...@@ -1622,7 +1622,7 @@ function FunctionSourceString(func) { ...@@ -1622,7 +1622,7 @@ function FunctionSourceString(func) {
throw MakeTypeError(kNotGeneric, 'Function.prototype.toString'); throw MakeTypeError(kNotGeneric, 'Function.prototype.toString');
} }
if (%FunctionIsBuiltin(func)) { if (%FunctionHidesSource(func)) {
return NativeCodeFunctionSourceString(func); return NativeCodeFunctionSourceString(func);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment