Move inlined function declarations and support from codegen.* to runtime.*.
Review URL: http://codereview.chromium.org/3293002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5451 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
2388079051
commit
fc83faa8fd
@ -271,10 +271,6 @@ class CodeGenerator: public AstVisitor {
|
|||||||
|
|
||||||
void AddDeferred(DeferredCode* code) { deferred_.Add(code); }
|
void AddDeferred(DeferredCode* code) { deferred_.Add(code); }
|
||||||
|
|
||||||
// If the name is an inline runtime function call return the number of
|
|
||||||
// expected arguments. Otherwise return -1.
|
|
||||||
static int InlineRuntimeCallArgumentsCount(Handle<String> name);
|
|
||||||
|
|
||||||
// Constants related to patching of inlined load/store.
|
// Constants related to patching of inlined load/store.
|
||||||
static int GetInlinedKeyedLoadInstructionsAfterPatch() {
|
static int GetInlinedKeyedLoadInstructionsAfterPatch() {
|
||||||
return FLAG_debug_code ? 32 : 13;
|
return FLAG_debug_code ? 32 : 13;
|
||||||
@ -290,6 +286,12 @@ class CodeGenerator: public AstVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Type of a member function that generates inline code for a native function.
|
||||||
|
typedef void (CodeGenerator::*InlineFunctionGenerator)
|
||||||
|
(ZoneList<Expression*>*);
|
||||||
|
|
||||||
|
static const InlineFunctionGenerator kInlineFunctionGenerators[];
|
||||||
|
|
||||||
// Construction/Destruction
|
// Construction/Destruction
|
||||||
explicit CodeGenerator(MacroAssembler* masm);
|
explicit CodeGenerator(MacroAssembler* masm);
|
||||||
|
|
||||||
@ -447,13 +449,9 @@ class CodeGenerator: public AstVisitor {
|
|||||||
void Branch(bool if_true, JumpTarget* target);
|
void Branch(bool if_true, JumpTarget* target);
|
||||||
void CheckStack();
|
void CheckStack();
|
||||||
|
|
||||||
struct InlineRuntimeLUT {
|
static InlineFunctionGenerator FindInlineFunctionGenerator(
|
||||||
void (CodeGenerator::*method)(ZoneList<Expression*>*);
|
Runtime::FunctionId function_id);
|
||||||
const char* name;
|
|
||||||
int nargs;
|
|
||||||
};
|
|
||||||
|
|
||||||
static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
|
|
||||||
bool CheckForInlineRuntimeCall(CallRuntime* node);
|
bool CheckForInlineRuntimeCall(CallRuntime* node);
|
||||||
|
|
||||||
static Handle<Code> ComputeLazyCompile(int argc);
|
static Handle<Code> ComputeLazyCompile(int argc);
|
||||||
@ -599,8 +597,6 @@ class CodeGenerator: public AstVisitor {
|
|||||||
// Size of inlined write barriers generated by EmitNamedStore.
|
// Size of inlined write barriers generated by EmitNamedStore.
|
||||||
static int inlined_write_barrier_size_;
|
static int inlined_write_barrier_size_;
|
||||||
|
|
||||||
static InlineRuntimeLUT kInlineRuntimeLUT[];
|
|
||||||
|
|
||||||
friend class VirtualFrame;
|
friend class VirtualFrame;
|
||||||
friend class JumpTarget;
|
friend class JumpTarget;
|
||||||
friend class Reference;
|
friend class Reference;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2009 the V8 project authors. All rights reserved.
|
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
@ -344,40 +344,35 @@ void CodeGenerator::VisitIncrementOperation(IncrementOperation* expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// List of special runtime calls which are generated inline. For some of these
|
// Lookup table for code generators for special runtime calls which are
|
||||||
// functions the code will be generated inline, and for others a call to a code
|
// generated inline.
|
||||||
// stub will be inlined.
|
#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \
|
||||||
|
&CodeGenerator::Generate##Name,
|
||||||
|
|
||||||
#define INLINE_RUNTIME_ENTRY(Name, argc, ressize) \
|
const CodeGenerator::InlineFunctionGenerator
|
||||||
{&CodeGenerator::Generate##Name, "_" #Name, argc}, \
|
CodeGenerator::kInlineFunctionGenerators[] = {
|
||||||
|
INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
|
||||||
CodeGenerator::InlineRuntimeLUT CodeGenerator::kInlineRuntimeLUT[] = {
|
INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
|
||||||
INLINE_RUNTIME_FUNCTION_LIST(INLINE_RUNTIME_ENTRY)
|
|
||||||
};
|
};
|
||||||
|
#undef INLINE_FUNCTION_GENERATOR_ADDRESS
|
||||||
|
|
||||||
#undef INLINE_RUNTIME_ENTRY
|
|
||||||
|
|
||||||
CodeGenerator::InlineRuntimeLUT* CodeGenerator::FindInlineRuntimeLUT(
|
CodeGenerator::InlineFunctionGenerator
|
||||||
Handle<String> name) {
|
CodeGenerator::FindInlineFunctionGenerator(Runtime::FunctionId id) {
|
||||||
const int entries_count =
|
return kInlineFunctionGenerators[
|
||||||
sizeof(kInlineRuntimeLUT) / sizeof(InlineRuntimeLUT);
|
static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction)];
|
||||||
for (int i = 0; i < entries_count; i++) {
|
|
||||||
InlineRuntimeLUT* entry = &kInlineRuntimeLUT[i];
|
|
||||||
if (name->IsEqualTo(CStrVector(entry->name))) {
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CodeGenerator::CheckForInlineRuntimeCall(CallRuntime* node) {
|
bool CodeGenerator::CheckForInlineRuntimeCall(CallRuntime* node) {
|
||||||
ZoneList<Expression*>* args = node->arguments();
|
ZoneList<Expression*>* args = node->arguments();
|
||||||
Handle<String> name = node->name();
|
Handle<String> name = node->name();
|
||||||
if (name->length() > 0 && name->Get(0) == '_') {
|
Runtime::Function* function = node->function();
|
||||||
InlineRuntimeLUT* entry = FindInlineRuntimeLUT(name);
|
if (function != NULL && function->intrinsic_type == Runtime::INLINE) {
|
||||||
if (entry != NULL) {
|
InlineFunctionGenerator generator =
|
||||||
((*this).*(entry->method))(args);
|
FindInlineFunctionGenerator(function->function_id);
|
||||||
|
if (generator != NULL) {
|
||||||
|
((*this).*(generator))(args);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -385,14 +380,6 @@ bool CodeGenerator::CheckForInlineRuntimeCall(CallRuntime* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int CodeGenerator::InlineRuntimeCallArgumentsCount(Handle<String> name) {
|
|
||||||
CodeGenerator::InlineRuntimeLUT* f =
|
|
||||||
CodeGenerator::FindInlineRuntimeLUT(name);
|
|
||||||
if (f != NULL) return f->nargs;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a
|
// Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a
|
||||||
// known result for the test expression, with no side effects.
|
// known result for the test expression, with no side effects.
|
||||||
CodeGenerator::ConditionAnalysis CodeGenerator::AnalyzeCondition(
|
CodeGenerator::ConditionAnalysis CodeGenerator::AnalyzeCondition(
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2006-2008 the V8 project authors. All rights reserved.
|
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
@ -71,48 +71,6 @@
|
|||||||
// CodeForDoWhileConditionPosition
|
// CodeForDoWhileConditionPosition
|
||||||
// CodeForSourcePosition
|
// CodeForSourcePosition
|
||||||
|
|
||||||
|
|
||||||
#define INLINE_RUNTIME_FUNCTION_LIST(F) \
|
|
||||||
F(IsSmi, 1, 1) \
|
|
||||||
F(IsNonNegativeSmi, 1, 1) \
|
|
||||||
F(IsArray, 1, 1) \
|
|
||||||
F(IsRegExp, 1, 1) \
|
|
||||||
F(CallFunction, -1 /* receiver + n args + function */, 1) \
|
|
||||||
F(IsConstructCall, 0, 1) \
|
|
||||||
F(ArgumentsLength, 0, 1) \
|
|
||||||
F(Arguments, 1, 1) \
|
|
||||||
F(ClassOf, 1, 1) \
|
|
||||||
F(ValueOf, 1, 1) \
|
|
||||||
F(SetValueOf, 2, 1) \
|
|
||||||
F(StringCharCodeAt, 2, 1) \
|
|
||||||
F(StringCharFromCode, 1, 1) \
|
|
||||||
F(StringCharAt, 2, 1) \
|
|
||||||
F(ObjectEquals, 2, 1) \
|
|
||||||
F(Log, 3, 1) \
|
|
||||||
F(RandomHeapNumber, 0, 1) \
|
|
||||||
F(IsObject, 1, 1) \
|
|
||||||
F(IsFunction, 1, 1) \
|
|
||||||
F(IsUndetectableObject, 1, 1) \
|
|
||||||
F(IsSpecObject, 1, 1) \
|
|
||||||
F(IsStringWrapperSafeForDefaultValueOf, 1, 1) \
|
|
||||||
F(StringAdd, 2, 1) \
|
|
||||||
F(SubString, 3, 1) \
|
|
||||||
F(StringCompare, 2, 1) \
|
|
||||||
F(RegExpExec, 4, 1) \
|
|
||||||
F(RegExpConstructResult, 3, 1) \
|
|
||||||
F(RegExpCloneResult, 1, 1) \
|
|
||||||
F(GetFromCache, 2, 1) \
|
|
||||||
F(NumberToString, 1, 1) \
|
|
||||||
F(SwapElements, 3, 1) \
|
|
||||||
F(MathPow, 2, 1) \
|
|
||||||
F(MathSin, 1, 1) \
|
|
||||||
F(MathCos, 1, 1) \
|
|
||||||
F(MathSqrt, 1, 1) \
|
|
||||||
F(IsRegExpEquivalent, 2, 1) \
|
|
||||||
F(HasCachedArrayIndex, 1, 1) \
|
|
||||||
F(GetCachedArrayIndex, 1, 1)
|
|
||||||
|
|
||||||
|
|
||||||
#if V8_TARGET_ARCH_IA32
|
#if V8_TARGET_ARCH_IA32
|
||||||
#include "ia32/codegen-ia32.h"
|
#include "ia32/codegen-ia32.h"
|
||||||
#elif V8_TARGET_ARCH_X64
|
#elif V8_TARGET_ARCH_X64
|
||||||
|
@ -505,18 +505,36 @@ void FullCodeGenerator::SetSourcePosition(int pos) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) {
|
// Lookup table for code generators for special runtime calls which are
|
||||||
Handle<String> name = expr->name();
|
// generated inline.
|
||||||
SmartPointer<char> cstring = name->ToCString();
|
#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \
|
||||||
|
&FullCodeGenerator::Emit##Name,
|
||||||
|
|
||||||
#define CHECK_EMIT_INLINE_CALL(name, x, y) \
|
const FullCodeGenerator::InlineFunctionGenerator
|
||||||
if (strcmp("_"#name, *cstring) == 0) { \
|
FullCodeGenerator::kInlineFunctionGenerators[] = {
|
||||||
Emit##name(expr->arguments()); \
|
INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
|
||||||
return; \
|
INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
|
||||||
}
|
};
|
||||||
INLINE_RUNTIME_FUNCTION_LIST(CHECK_EMIT_INLINE_CALL)
|
#undef INLINE_FUNCTION_GENERATOR_ADDRESS
|
||||||
#undef CHECK_EMIT_INLINE_CALL
|
|
||||||
UNREACHABLE();
|
|
||||||
|
FullCodeGenerator::InlineFunctionGenerator
|
||||||
|
FullCodeGenerator::FindInlineFunctionGenerator(Runtime::FunctionId id) {
|
||||||
|
return kInlineFunctionGenerators[
|
||||||
|
static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction)];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* node) {
|
||||||
|
ZoneList<Expression*>* args = node->arguments();
|
||||||
|
Handle<String> name = node->name();
|
||||||
|
Runtime::Function* function = node->function();
|
||||||
|
ASSERT(function != NULL);
|
||||||
|
ASSERT(function->intrinsic_type == Runtime::INLINE);
|
||||||
|
InlineFunctionGenerator generator =
|
||||||
|
FindInlineFunctionGenerator(function->function_id);
|
||||||
|
ASSERT(generator != NULL);
|
||||||
|
((*this).*(generator))(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -243,6 +243,12 @@ class FullCodeGenerator: public AstVisitor {
|
|||||||
kRightConstant
|
kRightConstant
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Type of a member function that generates inline code for a native function.
|
||||||
|
typedef void (FullCodeGenerator::*InlineFunctionGenerator)
|
||||||
|
(ZoneList<Expression*>*);
|
||||||
|
|
||||||
|
static const InlineFunctionGenerator kInlineFunctionGenerators[];
|
||||||
|
|
||||||
// Compute the frame pointer relative offset for a given local or
|
// Compute the frame pointer relative offset for a given local or
|
||||||
// parameter slot.
|
// parameter slot.
|
||||||
int SlotOffset(Slot* slot);
|
int SlotOffset(Slot* slot);
|
||||||
@ -373,10 +379,13 @@ class FullCodeGenerator: public AstVisitor {
|
|||||||
void EmitKeyedCallWithIC(Call* expr, Expression* key, RelocInfo::Mode mode);
|
void EmitKeyedCallWithIC(Call* expr, Expression* key, RelocInfo::Mode mode);
|
||||||
|
|
||||||
// Platform-specific code for inline runtime calls.
|
// Platform-specific code for inline runtime calls.
|
||||||
|
InlineFunctionGenerator FindInlineFunctionGenerator(Runtime::FunctionId id);
|
||||||
|
|
||||||
void EmitInlineRuntimeCall(CallRuntime* expr);
|
void EmitInlineRuntimeCall(CallRuntime* expr);
|
||||||
|
|
||||||
#define EMIT_INLINE_RUNTIME_CALL(name, x, y) \
|
#define EMIT_INLINE_RUNTIME_CALL(name, x, y) \
|
||||||
void Emit##name(ZoneList<Expression*>* arguments);
|
void Emit##name(ZoneList<Expression*>* arguments);
|
||||||
|
INLINE_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL)
|
||||||
INLINE_RUNTIME_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL)
|
INLINE_RUNTIME_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL)
|
||||||
#undef EMIT_INLINE_RUNTIME_CALL
|
#undef EMIT_INLINE_RUNTIME_CALL
|
||||||
|
|
||||||
|
@ -31,7 +31,6 @@
|
|||||||
#include "api.h"
|
#include "api.h"
|
||||||
#include "arguments.h"
|
#include "arguments.h"
|
||||||
#include "bootstrapper.h"
|
#include "bootstrapper.h"
|
||||||
#include "codegen.h"
|
|
||||||
#include "compiler.h"
|
#include "compiler.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "execution.h"
|
#include "execution.h"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2009 the V8 project authors. All rights reserved.
|
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
@ -1834,6 +1834,13 @@ bool Heap::CreateInitialObjects() {
|
|||||||
|
|
||||||
CreateFixedStubs();
|
CreateFixedStubs();
|
||||||
|
|
||||||
|
// Allocate the dictionary of intrinsic function names.
|
||||||
|
obj = StringDictionary::Allocate(Runtime::kNumFunctions);
|
||||||
|
if (obj->IsFailure()) return false;
|
||||||
|
obj = Runtime::InitializeIntrinsicFunctionNames(obj);
|
||||||
|
if (obj->IsFailure()) return false;
|
||||||
|
set_intrinsic_function_names(StringDictionary::cast(obj));
|
||||||
|
|
||||||
if (InitializeNumberStringCache()->IsFailure()) return false;
|
if (InitializeNumberStringCache()->IsFailure()) return false;
|
||||||
|
|
||||||
// Allocate cache for single character ASCII strings.
|
// Allocate cache for single character ASCII strings.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2006-2008 the V8 project authors. All rights reserved.
|
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
@ -114,6 +114,7 @@ namespace internal {
|
|||||||
V(Object, last_script_id, LastScriptId) \
|
V(Object, last_script_id, LastScriptId) \
|
||||||
V(Script, empty_script, EmptyScript) \
|
V(Script, empty_script, EmptyScript) \
|
||||||
V(Smi, real_stack_limit, RealStackLimit) \
|
V(Smi, real_stack_limit, RealStackLimit) \
|
||||||
|
V(StringDictionary, intrinsic_function_names, IntrinsicFunctionNames) \
|
||||||
|
|
||||||
#if V8_TARGET_ARCH_ARM && !V8_INTERPRETED_REGEXP
|
#if V8_TARGET_ARCH_ARM && !V8_INTERPRETED_REGEXP
|
||||||
#define STRONG_ROOT_LIST(V) \
|
#define STRONG_ROOT_LIST(V) \
|
||||||
|
@ -345,10 +345,6 @@ class CodeGenerator: public AstVisitor {
|
|||||||
bool in_spilled_code() const { return in_spilled_code_; }
|
bool in_spilled_code() const { return in_spilled_code_; }
|
||||||
void set_in_spilled_code(bool flag) { in_spilled_code_ = flag; }
|
void set_in_spilled_code(bool flag) { in_spilled_code_ = flag; }
|
||||||
|
|
||||||
// If the name is an inline runtime function call return the number of
|
|
||||||
// expected arguments. Otherwise return -1.
|
|
||||||
static int InlineRuntimeCallArgumentsCount(Handle<String> name);
|
|
||||||
|
|
||||||
// Return a position of the element at |index_as_smi| + |additional_offset|
|
// Return a position of the element at |index_as_smi| + |additional_offset|
|
||||||
// in FixedArray pointer to which is held in |array|. |index_as_smi| is Smi.
|
// in FixedArray pointer to which is held in |array|. |index_as_smi| is Smi.
|
||||||
static Operand FixedArrayElementOperand(Register array,
|
static Operand FixedArrayElementOperand(Register array,
|
||||||
@ -363,6 +359,12 @@ class CodeGenerator: public AstVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Type of a member function that generates inline code for a native function.
|
||||||
|
typedef void (CodeGenerator::*InlineFunctionGenerator)
|
||||||
|
(ZoneList<Expression*>*);
|
||||||
|
|
||||||
|
static const InlineFunctionGenerator kInlineFunctionGenerators[];
|
||||||
|
|
||||||
// Construction/Destruction
|
// Construction/Destruction
|
||||||
explicit CodeGenerator(MacroAssembler* masm);
|
explicit CodeGenerator(MacroAssembler* masm);
|
||||||
|
|
||||||
@ -624,13 +626,9 @@ class CodeGenerator: public AstVisitor {
|
|||||||
|
|
||||||
void CheckStack();
|
void CheckStack();
|
||||||
|
|
||||||
struct InlineRuntimeLUT {
|
static InlineFunctionGenerator FindInlineFunctionGenerator(
|
||||||
void (CodeGenerator::*method)(ZoneList<Expression*>*);
|
Runtime::FunctionId function_id);
|
||||||
const char* name;
|
|
||||||
int nargs;
|
|
||||||
};
|
|
||||||
|
|
||||||
static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
|
|
||||||
bool CheckForInlineRuntimeCall(CallRuntime* node);
|
bool CheckForInlineRuntimeCall(CallRuntime* node);
|
||||||
|
|
||||||
void ProcessDeclarations(ZoneList<Declaration*>* declarations);
|
void ProcessDeclarations(ZoneList<Declaration*>* declarations);
|
||||||
@ -792,8 +790,6 @@ class CodeGenerator: public AstVisitor {
|
|||||||
// in a spilled state.
|
// in a spilled state.
|
||||||
bool in_spilled_code_;
|
bool in_spilled_code_;
|
||||||
|
|
||||||
static InlineRuntimeLUT kInlineRuntimeLUT[];
|
|
||||||
|
|
||||||
friend class VirtualFrame;
|
friend class VirtualFrame;
|
||||||
friend class JumpTarget;
|
friend class JumpTarget;
|
||||||
friend class Reference;
|
friend class Reference;
|
||||||
|
@ -4243,58 +4243,43 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) {
|
|||||||
|
|
||||||
Expect(Token::MOD, CHECK_OK);
|
Expect(Token::MOD, CHECK_OK);
|
||||||
Handle<String> name = ParseIdentifier(CHECK_OK);
|
Handle<String> name = ParseIdentifier(CHECK_OK);
|
||||||
Runtime::Function* function =
|
|
||||||
Runtime::FunctionForName(scanner_.literal());
|
|
||||||
ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
|
ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
|
||||||
if (function == NULL && extension_ != NULL) {
|
if (is_pre_parsing_) return NULL;
|
||||||
|
|
||||||
|
if (extension_ != NULL) {
|
||||||
// The extension structures are only accessible while parsing the
|
// The extension structures are only accessible while parsing the
|
||||||
// very first time not when reparsing because of lazy compilation.
|
// very first time not when reparsing because of lazy compilation.
|
||||||
top_scope_->ForceEagerCompilation();
|
top_scope_->ForceEagerCompilation();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for built-in macros.
|
Runtime::Function* function = Runtime::FunctionForSymbol(name);
|
||||||
if (!is_pre_parsing_) {
|
|
||||||
if (function == Runtime::FunctionForId(Runtime::kIS_VAR)) {
|
// Check for built-in IS_VAR macro.
|
||||||
// %IS_VAR(x)
|
if (function != NULL &&
|
||||||
// evaluates to x if x is a variable,
|
function->intrinsic_type == Runtime::RUNTIME &&
|
||||||
// leads to a parse error otherwise
|
function->function_id == Runtime::kIS_VAR) {
|
||||||
|
// %IS_VAR(x) evaluates to x if x is a variable,
|
||||||
|
// leads to a parse error otherwise. Could be implemented as an
|
||||||
|
// inline function %_IS_VAR(x) to eliminate this special case.
|
||||||
if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
|
if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
|
||||||
return args->at(0);
|
return args->at(0);
|
||||||
}
|
} else {
|
||||||
*ok = false;
|
|
||||||
// Check here for other macros.
|
|
||||||
// } else if (function == Runtime::FunctionForId(Runtime::kIS_VAR)) {
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!*ok) {
|
|
||||||
// We found a macro but it failed.
|
|
||||||
ReportMessage("unable_to_parse", Vector<const char*>::empty());
|
ReportMessage("unable_to_parse", Vector<const char*>::empty());
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that the expected number arguments are passed to runtime functions.
|
|
||||||
if (!is_pre_parsing_) {
|
|
||||||
if (function != NULL
|
|
||||||
&& function->nargs != -1
|
|
||||||
&& function->nargs != args->length()) {
|
|
||||||
ReportMessage("illegal_access", Vector<const char*>::empty());
|
|
||||||
*ok = false;
|
|
||||||
return NULL;
|
|
||||||
} else if (function == NULL && !name.is_null()) {
|
|
||||||
// If this is not a runtime function implemented in C++ it might be an
|
|
||||||
// inlined runtime function.
|
|
||||||
int argc = CodeGenerator::InlineRuntimeCallArgumentsCount(name);
|
|
||||||
if (argc != -1 && argc != args->length()) {
|
|
||||||
ReportMessage("illegal_access", Vector<const char*>::empty());
|
|
||||||
*ok = false;
|
*ok = false;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that the expected number of arguments are being passed.
|
||||||
|
if (function != NULL &&
|
||||||
|
function->nargs != -1 &&
|
||||||
|
function->nargs != args->length()) {
|
||||||
|
ReportMessage("illegal_access", Vector<const char*>::empty());
|
||||||
|
*ok = false;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise we have a valid runtime call.
|
// We have a valid intrinsics call or a call to a builtin.
|
||||||
return NEW(CallRuntime(name, function, args));
|
return NEW(CallRuntime(name, function, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4519,7 +4519,6 @@ static Object* Runtime_StringParseInt(Arguments args) {
|
|||||||
RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
|
RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
|
||||||
double value = StringToInt(s, radix);
|
double value = StringToInt(s, radix);
|
||||||
return Heap::NumberFromDouble(value);
|
return Heap::NumberFromDouble(value);
|
||||||
return Heap::nan_value();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -10064,6 +10063,7 @@ static Object* Runtime_ListNatives(Arguments args) {
|
|||||||
inline_runtime_functions = false;
|
inline_runtime_functions = false;
|
||||||
RUNTIME_FUNCTION_LIST(ADD_ENTRY)
|
RUNTIME_FUNCTION_LIST(ADD_ENTRY)
|
||||||
inline_runtime_functions = true;
|
inline_runtime_functions = true;
|
||||||
|
INLINE_FUNCTION_LIST(ADD_ENTRY)
|
||||||
INLINE_RUNTIME_FUNCTION_LIST(ADD_ENTRY)
|
INLINE_RUNTIME_FUNCTION_LIST(ADD_ENTRY)
|
||||||
#undef ADD_ENTRY
|
#undef ADD_ENTRY
|
||||||
return *result;
|
return *result;
|
||||||
@ -10090,35 +10090,58 @@ static Object* Runtime_IS_VAR(Arguments args) {
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Implementation of Runtime
|
// Implementation of Runtime
|
||||||
|
|
||||||
#define F(name, nargs, ressize) \
|
#define F(name, number_of_args, result_size) \
|
||||||
{ #name, FUNCTION_ADDR(Runtime_##name), nargs, \
|
{ Runtime::k##name, Runtime::RUNTIME, #name, \
|
||||||
static_cast<int>(Runtime::k##name), ressize },
|
FUNCTION_ADDR(Runtime_##name), number_of_args, result_size },
|
||||||
|
|
||||||
static Runtime::Function Runtime_functions[] = {
|
|
||||||
|
#define I(name, number_of_args, result_size) \
|
||||||
|
{ Runtime::kInline##name, Runtime::INLINE, \
|
||||||
|
"_" #name, NULL, number_of_args, result_size },
|
||||||
|
|
||||||
|
Runtime::Function kIntrinsicFunctions[] = {
|
||||||
RUNTIME_FUNCTION_LIST(F)
|
RUNTIME_FUNCTION_LIST(F)
|
||||||
{ NULL, NULL, 0, -1, 0 }
|
INLINE_FUNCTION_LIST(I)
|
||||||
|
INLINE_RUNTIME_FUNCTION_LIST(I)
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef F
|
|
||||||
|
const int Runtime::kNotFound;
|
||||||
|
|
||||||
|
|
||||||
Runtime::Function* Runtime::FunctionForId(FunctionId fid) {
|
Object* Runtime::InitializeIntrinsicFunctionNames(Object* dictionary) {
|
||||||
ASSERT(0 <= fid && fid < kNofFunctions);
|
ASSERT(dictionary != NULL);
|
||||||
return &Runtime_functions[fid];
|
ASSERT(StringDictionary::cast(dictionary)->NumberOfElements() == 0);
|
||||||
|
for (int i = 0; i < kNumFunctions; ++i) {
|
||||||
|
Object* name_symbol = Heap::LookupAsciiSymbol(kIntrinsicFunctions[i].name);
|
||||||
|
if (name_symbol->IsFailure()) return name_symbol;
|
||||||
|
StringDictionary* string_dictionary = StringDictionary::cast(dictionary);
|
||||||
|
dictionary = string_dictionary->Add(String::cast(name_symbol),
|
||||||
|
Smi::FromInt(i),
|
||||||
|
PropertyDetails(NONE, NORMAL));
|
||||||
|
// Non-recoverable failure. Calling code must restart heap initialization.
|
||||||
|
if (dictionary->IsFailure()) return dictionary;
|
||||||
|
}
|
||||||
|
return dictionary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Runtime::Function* Runtime::FunctionForName(Vector<const char> name) {
|
Runtime::Function* Runtime::FunctionForSymbol(Handle<String> name) {
|
||||||
for (Function* f = Runtime_functions; f->name != NULL; f++) {
|
int entry = Heap::intrinsic_function_names()->FindEntry(*name);
|
||||||
if (strncmp(f->name, name.start(), name.length()) == 0
|
if (entry != kNotFound) {
|
||||||
&& f->name[name.length()] == 0) {
|
Object* smi_index = Heap::intrinsic_function_names()->ValueAt(entry);
|
||||||
return f;
|
int function_index = Smi::cast(smi_index)->value();
|
||||||
}
|
return &(kIntrinsicFunctions[function_index]);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
|
||||||
|
return &(kIntrinsicFunctions[static_cast<int>(id)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Runtime::PerformGC(Object* result) {
|
void Runtime::PerformGC(Object* result) {
|
||||||
Failure* failure = Failure::cast(result);
|
Failure* failure = Failure::cast(result);
|
||||||
if (failure->IsRetryAfterGC()) {
|
if (failure->IsRetryAfterGC()) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2006-2008 the V8 project authors. All rights reserved.
|
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
// met:
|
// met:
|
||||||
@ -389,6 +389,59 @@ namespace internal {
|
|||||||
RUNTIME_FUNCTION_LIST_PROFILER_SUPPORT(F)
|
RUNTIME_FUNCTION_LIST_PROFILER_SUPPORT(F)
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
// INLINE_FUNCTION_LIST defines all inlined functions accessed
|
||||||
|
// with a native call of the form %_name from within JS code.
|
||||||
|
// Entries have the form F(name, number of arguments, number of return values).
|
||||||
|
#define INLINE_FUNCTION_LIST(F) \
|
||||||
|
F(IsSmi, 1, 1) \
|
||||||
|
F(IsNonNegativeSmi, 1, 1) \
|
||||||
|
F(IsArray, 1, 1) \
|
||||||
|
F(IsRegExp, 1, 1) \
|
||||||
|
F(CallFunction, -1 /* receiver + n args + function */, 1) \
|
||||||
|
F(ArgumentsLength, 0, 1) \
|
||||||
|
F(Arguments, 1, 1) \
|
||||||
|
F(ValueOf, 1, 1) \
|
||||||
|
F(SetValueOf, 2, 1) \
|
||||||
|
F(StringCharFromCode, 1, 1) \
|
||||||
|
F(StringCharAt, 2, 1) \
|
||||||
|
F(ObjectEquals, 2, 1) \
|
||||||
|
F(RandomHeapNumber, 0, 1) \
|
||||||
|
F(IsObject, 1, 1) \
|
||||||
|
F(IsFunction, 1, 1) \
|
||||||
|
F(IsUndetectableObject, 1, 1) \
|
||||||
|
F(IsSpecObject, 1, 1) \
|
||||||
|
F(IsStringWrapperSafeForDefaultValueOf, 1, 1) \
|
||||||
|
F(MathPow, 2, 1) \
|
||||||
|
F(MathSin, 1, 1) \
|
||||||
|
F(MathCos, 1, 1) \
|
||||||
|
F(MathSqrt, 1, 1) \
|
||||||
|
F(IsRegExpEquivalent, 2, 1) \
|
||||||
|
F(HasCachedArrayIndex, 1, 1) \
|
||||||
|
F(GetCachedArrayIndex, 1, 1)
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// INLINE_AND_RUNTIME_FUNCTION_LIST defines all inlined functions accessed
|
||||||
|
// with a native call of the form %_name from within JS code that also have
|
||||||
|
// a corresponding runtime function, that is called for slow cases.
|
||||||
|
// Entries have the form F(name, number of arguments, number of return values).
|
||||||
|
#define INLINE_RUNTIME_FUNCTION_LIST(F) \
|
||||||
|
F(IsConstructCall, 0, 1) \
|
||||||
|
F(ClassOf, 1, 1) \
|
||||||
|
F(StringCharCodeAt, 2, 1) \
|
||||||
|
F(Log, 3, 1) \
|
||||||
|
F(StringAdd, 2, 1) \
|
||||||
|
F(SubString, 3, 1) \
|
||||||
|
F(StringCompare, 2, 1) \
|
||||||
|
F(RegExpExec, 4, 1) \
|
||||||
|
F(RegExpConstructResult, 3, 1) \
|
||||||
|
F(RegExpCloneResult, 1, 1) \
|
||||||
|
F(GetFromCache, 2, 1) \
|
||||||
|
F(NumberToString, 1, 1) \
|
||||||
|
F(SwapElements, 3, 1)
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
// Runtime provides access to all C++ runtime functions.
|
// Runtime provides access to all C++ runtime functions.
|
||||||
|
|
||||||
class Runtime : public AllStatic {
|
class Runtime : public AllStatic {
|
||||||
@ -396,33 +449,52 @@ class Runtime : public AllStatic {
|
|||||||
enum FunctionId {
|
enum FunctionId {
|
||||||
#define F(name, nargs, ressize) k##name,
|
#define F(name, nargs, ressize) k##name,
|
||||||
RUNTIME_FUNCTION_LIST(F)
|
RUNTIME_FUNCTION_LIST(F)
|
||||||
kNofFunctions
|
|
||||||
#undef F
|
#undef F
|
||||||
|
#define F(name, nargs, ressize) kInline##name,
|
||||||
|
INLINE_FUNCTION_LIST(F)
|
||||||
|
INLINE_RUNTIME_FUNCTION_LIST(F)
|
||||||
|
#undef F
|
||||||
|
kNumFunctions,
|
||||||
|
kFirstInlineFunction = kInlineIsSmi
|
||||||
};
|
};
|
||||||
|
|
||||||
// Runtime function descriptor.
|
enum IntrinsicType {
|
||||||
|
RUNTIME,
|
||||||
|
INLINE
|
||||||
|
};
|
||||||
|
|
||||||
|
// Intrinsic function descriptor.
|
||||||
struct Function {
|
struct Function {
|
||||||
|
FunctionId function_id;
|
||||||
|
IntrinsicType intrinsic_type;
|
||||||
// The JS name of the function.
|
// The JS name of the function.
|
||||||
const char* name;
|
const char* name;
|
||||||
|
|
||||||
// The C++ (native) entry point.
|
// The C++ (native) entry point. NULL if the function is inlined.
|
||||||
byte* entry;
|
byte* entry;
|
||||||
|
|
||||||
// The number of arguments expected; nargs < 0 if variable no. of
|
// The number of arguments expected. nargs is -1 if the function takes
|
||||||
// arguments.
|
// a variable number of arguments.
|
||||||
int nargs;
|
int nargs;
|
||||||
int stub_id;
|
// Size of result. Most functions return a single pointer, size 1.
|
||||||
// Size of result, if complex (larger than a single pointer),
|
|
||||||
// otherwise zero.
|
|
||||||
int result_size;
|
int result_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the runtime function with the given function id.
|
static const int kNotFound = -1;
|
||||||
static Function* FunctionForId(FunctionId fid);
|
|
||||||
|
|
||||||
// Get the runtime function with the given name.
|
// Add symbols for all the intrinsic function names to a StringDictionary.
|
||||||
static Function* FunctionForName(Vector<const char> name);
|
// Returns failure if an allocation fails. In this case, it must be
|
||||||
|
// retried with a new, empty StringDictionary, not with the same one.
|
||||||
|
// Alternatively, heap initialization can be completely restarted.
|
||||||
|
static Object* InitializeIntrinsicFunctionNames(Object* dictionary);
|
||||||
|
|
||||||
|
// Get the intrinsic function with the given name, which must be a symbol.
|
||||||
|
static Function* FunctionForSymbol(Handle<String> name);
|
||||||
|
|
||||||
|
// Get the intrinsic function with the given FunctionId.
|
||||||
|
static Function* FunctionForId(FunctionId id);
|
||||||
|
|
||||||
|
// General-purpose helper functions for runtime system.
|
||||||
static int StringMatch(Handle<String> sub, Handle<String> pat, int index);
|
static int StringMatch(Handle<String> sub, Handle<String> pat, int index);
|
||||||
|
|
||||||
static bool IsUpperCaseChar(uint16_t ch);
|
static bool IsUpperCaseChar(uint16_t ch);
|
||||||
|
@ -343,15 +343,17 @@ class CodeGenerator: public AstVisitor {
|
|||||||
bool in_spilled_code() const { return in_spilled_code_; }
|
bool in_spilled_code() const { return in_spilled_code_; }
|
||||||
void set_in_spilled_code(bool flag) { in_spilled_code_ = flag; }
|
void set_in_spilled_code(bool flag) { in_spilled_code_ = flag; }
|
||||||
|
|
||||||
// If the name is an inline runtime function call return the number of
|
|
||||||
// expected arguments. Otherwise return -1.
|
|
||||||
static int InlineRuntimeCallArgumentsCount(Handle<String> name);
|
|
||||||
|
|
||||||
static Operand ContextOperand(Register context, int index) {
|
static Operand ContextOperand(Register context, int index) {
|
||||||
return Operand(context, Context::SlotOffset(index));
|
return Operand(context, Context::SlotOffset(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Type of a member function that generates inline code for a native function.
|
||||||
|
typedef void (CodeGenerator::*InlineFunctionGenerator)
|
||||||
|
(ZoneList<Expression*>*);
|
||||||
|
|
||||||
|
static const InlineFunctionGenerator kInlineFunctionGenerators[];
|
||||||
|
|
||||||
// Construction/Destruction
|
// Construction/Destruction
|
||||||
explicit CodeGenerator(MacroAssembler* masm);
|
explicit CodeGenerator(MacroAssembler* masm);
|
||||||
|
|
||||||
@ -584,12 +586,9 @@ class CodeGenerator: public AstVisitor {
|
|||||||
|
|
||||||
void CheckStack();
|
void CheckStack();
|
||||||
|
|
||||||
struct InlineRuntimeLUT {
|
static InlineFunctionGenerator FindInlineFunctionGenerator(
|
||||||
void (CodeGenerator::*method)(ZoneList<Expression*>*);
|
Runtime::FunctionId function_id);
|
||||||
const char* name;
|
|
||||||
int nargs;
|
|
||||||
};
|
|
||||||
static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
|
|
||||||
bool CheckForInlineRuntimeCall(CallRuntime* node);
|
bool CheckForInlineRuntimeCall(CallRuntime* node);
|
||||||
|
|
||||||
void ProcessDeclarations(ZoneList<Declaration*>* declarations);
|
void ProcessDeclarations(ZoneList<Declaration*>* declarations);
|
||||||
@ -742,8 +741,6 @@ class CodeGenerator: public AstVisitor {
|
|||||||
// in a spilled state.
|
// in a spilled state.
|
||||||
bool in_spilled_code_;
|
bool in_spilled_code_;
|
||||||
|
|
||||||
static InlineRuntimeLUT kInlineRuntimeLUT[];
|
|
||||||
|
|
||||||
friend class VirtualFrame;
|
friend class VirtualFrame;
|
||||||
friend class JumpTarget;
|
friend class JumpTarget;
|
||||||
friend class Reference;
|
friend class Reference;
|
||||||
|
Loading…
Reference in New Issue
Block a user