Port CallSite methods to C++.

The goal is to port all of error stack trace formatting to C++.
We will do this bottom up, by first porting helper functions.

Eventually, CallSite methods will only be used when a custom
error stack trace formatter is defined via Error.prepareStackTrace.

R=jkummerow@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#28095}
This commit is contained in:
yangguo 2015-04-28 01:53:12 -07:00 committed by Commit bot
parent 3be656fb55
commit 4d12e94801
7 changed files with 217 additions and 88 deletions

View File

@ -163,6 +163,85 @@ SmartArrayPointer<char> MessageHandler::GetLocalizedMessage(
}
Handle<Object> CallSite::GetFileName(Isolate* isolate) {
Handle<Object> script(fun_->shared()->script(), isolate);
if (script->IsScript()) {
return Handle<Object>(Handle<Script>::cast(script)->name(), isolate);
}
return isolate->factory()->null_value();
}
Handle<Object> CallSite::GetFunctionName(Isolate* isolate) {
Handle<String> result = JSFunction::GetDebugName(fun_);
if (result->length() != 0) return result;
Handle<Object> script(fun_->shared()->script(), isolate);
if (script->IsScript() &&
Handle<Script>::cast(script)->compilation_type() ==
Script::COMPILATION_TYPE_EVAL) {
return isolate->factory()->eval_string();
}
return isolate->factory()->null_value();
}
Handle<Object> CallSite::GetScriptNameOrSourceUrl(Isolate* isolate) {
Handle<Object> script_obj(fun_->shared()->script(), isolate);
if (script_obj->IsScript()) {
Handle<Script> script = Handle<Script>::cast(script_obj);
Object* source_url = script->source_url();
if (source_url->IsString()) return Handle<Object>(source_url, isolate);
return Handle<Object>(script->name(), isolate);
}
return isolate->factory()->null_value();
}
int CallSite::GetLineNumber(Isolate* isolate) {
if (pos_ >= 0) {
Handle<Object> script_obj(fun_->shared()->script(), isolate);
if (script_obj->IsScript()) {
Handle<Script> script = Handle<Script>::cast(script_obj);
return Script::GetLineNumber(script, pos_) + 1;
}
}
return -1;
}
int CallSite::GetColumnNumber(Isolate* isolate) {
if (pos_ >= 0) {
Handle<Object> script_obj(fun_->shared()->script(), isolate);
if (script_obj->IsScript()) {
Handle<Script> script = Handle<Script>::cast(script_obj);
return Script::GetColumnNumber(script, pos_) + 1;
}
}
return -1;
}
bool CallSite::IsNative(Isolate* isolate) {
Handle<Object> script(fun_->shared()->script(), isolate);
return script->IsScript() &&
Handle<Script>::cast(script)->type()->value() == Script::TYPE_NATIVE;
}
bool CallSite::IsToplevel(Isolate* isolate) {
return receiver_->IsJSGlobalProxy() || receiver_->IsNull() ||
receiver_->IsUndefined();
}
bool CallSite::IsEval(Isolate* isolate) {
Handle<Object> script(fun_->shared()->script(), isolate);
return script->IsScript() &&
Handle<Script>::cast(script)->compilation_type() ==
Script::COMPILATION_TYPE_EVAL;
}
MaybeHandle<String> MessageTemplate::FormatMessage(int template_index,
Handle<String> arg0,
Handle<String> arg1,

View File

@ -88,6 +88,29 @@ class MessageHandler {
};
class CallSite {
public:
CallSite(Handle<Object> receiver, Handle<JSFunction> fun, int pos)
: receiver_(receiver), fun_(fun), pos_(pos) {}
Handle<Object> GetFileName(Isolate* isolate);
Handle<Object> GetFunctionName(Isolate* isolate);
Handle<Object> GetScriptNameOrSourceUrl(Isolate* isolate);
// Return 1-based line number, including line offset.
int GetLineNumber(Isolate* isolate);
// Return 1-based column number, including column offset if first line.
int GetColumnNumber(Isolate* isolate);
bool IsNative(Isolate* isolate);
bool IsToplevel(Isolate* isolate);
bool IsEval(Isolate* isolate);
private:
Handle<Object> receiver_;
Handle<JSFunction> fun_;
int pos_;
};
#define MESSAGE_TEMPLATES(T) \
/* Error */ \
T(CyclicProto, "Cyclic __proto__ value") \

View File

@ -737,20 +737,31 @@ function CallSiteGetThis() {
? UNDEFINED : GET_PRIVATE(this, CallSiteReceiverKey);
}
function CallSiteGetFunction() {
return GET_PRIVATE(this, CallSiteStrictModeKey)
? UNDEFINED : GET_PRIVATE(this, CallSiteFunctionKey);
}
function CallSiteGetPosition() {
return GET_PRIVATE(this, CallSitePositionKey);
}
function CallSiteGetTypeName() {
return GetTypeName(GET_PRIVATE(this, CallSiteReceiverKey), false);
}
function CallSiteIsToplevel() {
if (GET_PRIVATE(this, CallSiteReceiverKey) == null) {
return true;
}
return IS_GLOBAL(GET_PRIVATE(this, CallSiteReceiverKey));
var receiver = GET_PRIVATE(this, CallSiteReceiverKey);
var fun = GET_PRIVATE(this, CallSiteFunctionKey);
var pos = GET_PRIVATE(this, CallSitePositionKey);
return %CallSiteIsToplevelRT(receiver, fun, pos);
}
function CallSiteIsEval() {
var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
return script && script.compilation_type == COMPILATION_TYPE_EVAL;
var receiver = GET_PRIVATE(this, CallSiteReceiverKey);
var fun = GET_PRIVATE(this, CallSiteFunctionKey);
var pos = GET_PRIVATE(this, CallSitePositionKey);
return %CallSiteIsEvalRT(receiver, fun, pos);
}
function CallSiteGetEvalOrigin() {
@ -759,28 +770,18 @@ function CallSiteGetEvalOrigin() {
}
function CallSiteGetScriptNameOrSourceURL() {
var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
return script ? script.nameOrSourceURL() : null;
}
function CallSiteGetFunction() {
return GET_PRIVATE(this, CallSiteStrictModeKey)
? UNDEFINED : GET_PRIVATE(this, CallSiteFunctionKey);
var receiver = GET_PRIVATE(this, CallSiteReceiverKey);
var fun = GET_PRIVATE(this, CallSiteFunctionKey);
var pos = GET_PRIVATE(this, CallSitePositionKey);
return %CallSiteGetScriptNameOrSourceUrlRT(receiver, fun, pos);
}
function CallSiteGetFunctionName() {
// See if the function knows its own name
var receiver = GET_PRIVATE(this, CallSiteReceiverKey);
var fun = GET_PRIVATE(this, CallSiteFunctionKey);
var name = %FunctionGetDebugName(fun);
if (name) {
return name;
}
// Maybe this is an evaluation?
var script = %FunctionGetScript(fun);
if (script && script.compilation_type == COMPILATION_TYPE_EVAL) {
return "eval";
}
return null;
var pos = GET_PRIVATE(this, CallSitePositionKey);
return %CallSiteGetFunctionNameRT(receiver, fun, pos);
}
function CallSiteGetMethodName() {
@ -816,43 +817,31 @@ function CallSiteGetMethodName() {
}
function CallSiteGetFileName() {
var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
return script ? script.name : null;
var receiver = GET_PRIVATE(this, CallSiteReceiverKey);
var fun = GET_PRIVATE(this, CallSiteFunctionKey);
var pos = GET_PRIVATE(this, CallSitePositionKey);
return %CallSiteGetFileNameRT(receiver, fun, pos);
}
function CallSiteGetLineNumber() {
if (GET_PRIVATE(this, CallSitePositionKey) == -1) {
return null;
}
var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
var location = null;
if (script) {
location = script.locationFromPosition(
GET_PRIVATE(this, CallSitePositionKey), true);
}
return location ? location.line + 1 : null;
var receiver = GET_PRIVATE(this, CallSiteReceiverKey);
var fun = GET_PRIVATE(this, CallSiteFunctionKey);
var pos = GET_PRIVATE(this, CallSitePositionKey);
return %CallSiteGetLineNumberRT(receiver, fun, pos);
}
function CallSiteGetColumnNumber() {
if (GET_PRIVATE(this, CallSitePositionKey) == -1) {
return null;
}
var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
var location = null;
if (script) {
location = script.locationFromPosition(
GET_PRIVATE(this, CallSitePositionKey), true);
}
return location ? location.column + 1: null;
var receiver = GET_PRIVATE(this, CallSiteReceiverKey);
var fun = GET_PRIVATE(this, CallSiteFunctionKey);
var pos = GET_PRIVATE(this, CallSitePositionKey);
return %CallSiteGetColumnNumberRT(receiver, fun, pos);
}
function CallSiteIsNative() {
var script = %FunctionGetScript(GET_PRIVATE(this, CallSiteFunctionKey));
return script ? (script.type == TYPE_NATIVE) : false;
}
function CallSiteGetPosition() {
return GET_PRIVATE(this, CallSitePositionKey);
var receiver = GET_PRIVATE(this, CallSiteReceiverKey);
var fun = GET_PRIVATE(this, CallSiteFunctionKey);
var pos = GET_PRIVATE(this, CallSitePositionKey);
return %CallSiteIsNativeRT(receiver, fun, pos);
}
function CallSiteIsConstructor() {

View File

@ -2770,15 +2770,6 @@ RUNTIME_FUNCTION(Runtime_FunctionGetInferredName) {
}
RUNTIME_FUNCTION(Runtime_FunctionGetDebugName) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, f, 0);
return *JSFunction::GetDebugName(f);
}
// A testing entry. Returns statement position which is the closest to
// source_position.
RUNTIME_FUNCTION(Runtime_GetFunctionCodePositionFromSource) {

View File

@ -322,6 +322,47 @@ RUNTIME_FUNCTION(Runtime_FormatMessageString) {
}
#define CALLSITE_GET(NAME, RETURN) \
RUNTIME_FUNCTION(Runtime_CallSite##NAME##RT) { \
HandleScope scope(isolate); \
DCHECK(args.length() == 3); \
CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0); \
CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 1); \
CONVERT_INT32_ARG_CHECKED(pos, 2); \
Handle<String> result; \
CallSite call_site(receiver, fun, pos); \
return RETURN(call_site.NAME(isolate), isolate); \
}
static inline Object* ReturnDereferencedHandle(Handle<Object> obj,
Isolate* isolate) {
return *obj;
}
static inline Object* ReturnPositiveSmiOrNull(int value, Isolate* isolate) {
if (value >= 0) return Smi::FromInt(value);
return isolate->heap()->null_value();
}
static inline Object* ReturnBoolean(bool value, Isolate* isolate) {
return isolate->heap()->ToBoolean(value);
}
CALLSITE_GET(GetFileName, ReturnDereferencedHandle)
CALLSITE_GET(GetFunctionName, ReturnDereferencedHandle)
CALLSITE_GET(GetScriptNameOrSourceUrl, ReturnDereferencedHandle)
CALLSITE_GET(GetLineNumber, ReturnPositiveSmiOrNull)
CALLSITE_GET(GetColumnNumber, ReturnPositiveSmiOrNull)
CALLSITE_GET(IsNative, ReturnBoolean)
CALLSITE_GET(IsToplevel, ReturnBoolean)
CALLSITE_GET(IsEval, ReturnBoolean)
#undef CALLSITE_GET
RUNTIME_FUNCTION(Runtime_IS_VAR) {
UNREACHABLE(); // implemented as macro in the parser
return NULL;

View File

@ -170,7 +170,6 @@ namespace internal {
F(DebugGetPrototype, 1, 1) \
F(DebugSetScriptSource, 2, 1) \
F(FunctionGetInferredName, 1, 1) \
F(FunctionGetDebugName, 1, 1) \
F(GetFunctionCodePositionFromSource, 2, 1) \
F(ExecuteInDebugContext, 1, 1) \
F(GetDebugContext, 0, 1) \
@ -267,32 +266,40 @@ namespace internal {
#endif
#define FOR_EACH_INTRINSIC_INTERNAL(F) \
F(CheckIsBootstrapping, 0, 1) \
F(Throw, 1, 1) \
F(ReThrow, 1, 1) \
F(FindExceptionHandler, 0, 1) \
F(PromoteScheduledException, 0, 1) \
F(ThrowReferenceError, 1, 1) \
F(ThrowIteratorResultNotAnObject, 1, 1) \
F(PromiseRejectEvent, 3, 1) \
F(PromiseRevokeReject, 1, 1) \
F(PromiseHasHandlerSymbol, 0, 1) \
F(StackGuard, 0, 1) \
F(Interrupt, 0, 1) \
F(AllocateInNewSpace, 1, 1) \
F(AllocateInTargetSpace, 2, 1) \
F(CollectStackTrace, 2, 1) \
F(RenderCallSite, 0, 1) \
F(GetFromCacheRT, 2, 1) \
F(MessageGetStartPosition, 1, 1) \
F(MessageGetScript, 1, 1) \
F(FormatMessageString, 4, 1) \
F(IS_VAR, 1, 1) \
F(GetFromCache, 2, 1) \
F(IncrementStatsCounter, 1, 1) \
F(Likely, 1, 1) \
F(Unlikely, 1, 1) \
#define FOR_EACH_INTRINSIC_INTERNAL(F) \
F(CheckIsBootstrapping, 0, 1) \
F(Throw, 1, 1) \
F(ReThrow, 1, 1) \
F(FindExceptionHandler, 0, 1) \
F(PromoteScheduledException, 0, 1) \
F(ThrowReferenceError, 1, 1) \
F(ThrowIteratorResultNotAnObject, 1, 1) \
F(PromiseRejectEvent, 3, 1) \
F(PromiseRevokeReject, 1, 1) \
F(PromiseHasHandlerSymbol, 0, 1) \
F(StackGuard, 0, 1) \
F(Interrupt, 0, 1) \
F(AllocateInNewSpace, 1, 1) \
F(AllocateInTargetSpace, 2, 1) \
F(CollectStackTrace, 2, 1) \
F(RenderCallSite, 0, 1) \
F(GetFromCacheRT, 2, 1) \
F(MessageGetStartPosition, 1, 1) \
F(MessageGetScript, 1, 1) \
F(FormatMessageString, 4, 1) \
F(CallSiteGetFileNameRT, 3, 1) \
F(CallSiteGetFunctionNameRT, 3, 1) \
F(CallSiteGetScriptNameOrSourceUrlRT, 3, 1) \
F(CallSiteGetLineNumberRT, 3, 1) \
F(CallSiteGetColumnNumberRT, 3, 1) \
F(CallSiteIsNativeRT, 3, 1) \
F(CallSiteIsToplevelRT, 3, 1) \
F(CallSiteIsEvalRT, 3, 1) \
F(IS_VAR, 1, 1) \
F(GetFromCache, 2, 1) \
F(IncrementStatsCounter, 1, 1) \
F(Likely, 1, 1) \
F(Unlikely, 1, 1) \
F(HarmonyToString, 0, 1)

View File

@ -48,5 +48,4 @@ try {
assertTrue(p1 != -1);
assertTrue(p3 < p2);
assertTrue(p2 < p1);
print(stack);
}