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:
whesse@chromium.org 2010-09-14 14:52:53 +00:00
parent 2388079051
commit fc83faa8fd
13 changed files with 242 additions and 194 deletions

View File

@ -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;

View File

@ -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(

View File

@ -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

View File

@ -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);
} }

View File

@ -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

View File

@ -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"

View File

@ -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.

View File

@ -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) \

View File

@ -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;

View File

@ -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));
} }

View File

@ -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()) {

View File

@ -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);

View File

@ -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;