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); }
|
||||
|
||||
// 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.
|
||||
static int GetInlinedKeyedLoadInstructionsAfterPatch() {
|
||||
return FLAG_debug_code ? 32 : 13;
|
||||
@ -290,6 +286,12 @@ class CodeGenerator: public AstVisitor {
|
||||
}
|
||||
|
||||
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
|
||||
explicit CodeGenerator(MacroAssembler* masm);
|
||||
|
||||
@ -447,13 +449,9 @@ class CodeGenerator: public AstVisitor {
|
||||
void Branch(bool if_true, JumpTarget* target);
|
||||
void CheckStack();
|
||||
|
||||
struct InlineRuntimeLUT {
|
||||
void (CodeGenerator::*method)(ZoneList<Expression*>*);
|
||||
const char* name;
|
||||
int nargs;
|
||||
};
|
||||
static InlineFunctionGenerator FindInlineFunctionGenerator(
|
||||
Runtime::FunctionId function_id);
|
||||
|
||||
static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
|
||||
bool CheckForInlineRuntimeCall(CallRuntime* node);
|
||||
|
||||
static Handle<Code> ComputeLazyCompile(int argc);
|
||||
@ -599,8 +597,6 @@ class CodeGenerator: public AstVisitor {
|
||||
// Size of inlined write barriers generated by EmitNamedStore.
|
||||
static int inlined_write_barrier_size_;
|
||||
|
||||
static InlineRuntimeLUT kInlineRuntimeLUT[];
|
||||
|
||||
friend class VirtualFrame;
|
||||
friend class JumpTarget;
|
||||
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
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
@ -344,40 +344,35 @@ void CodeGenerator::VisitIncrementOperation(IncrementOperation* expr) {
|
||||
}
|
||||
|
||||
|
||||
// List of special runtime calls which are generated inline. For some of these
|
||||
// functions the code will be generated inline, and for others a call to a code
|
||||
// stub will be inlined.
|
||||
// Lookup table for code generators for special runtime calls which are
|
||||
// generated inline.
|
||||
#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \
|
||||
&CodeGenerator::Generate##Name,
|
||||
|
||||
#define INLINE_RUNTIME_ENTRY(Name, argc, ressize) \
|
||||
{&CodeGenerator::Generate##Name, "_" #Name, argc}, \
|
||||
|
||||
CodeGenerator::InlineRuntimeLUT CodeGenerator::kInlineRuntimeLUT[] = {
|
||||
INLINE_RUNTIME_FUNCTION_LIST(INLINE_RUNTIME_ENTRY)
|
||||
const CodeGenerator::InlineFunctionGenerator
|
||||
CodeGenerator::kInlineFunctionGenerators[] = {
|
||||
INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
|
||||
INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
|
||||
};
|
||||
#undef INLINE_FUNCTION_GENERATOR_ADDRESS
|
||||
|
||||
#undef INLINE_RUNTIME_ENTRY
|
||||
|
||||
CodeGenerator::InlineRuntimeLUT* CodeGenerator::FindInlineRuntimeLUT(
|
||||
Handle<String> name) {
|
||||
const int entries_count =
|
||||
sizeof(kInlineRuntimeLUT) / sizeof(InlineRuntimeLUT);
|
||||
for (int i = 0; i < entries_count; i++) {
|
||||
InlineRuntimeLUT* entry = &kInlineRuntimeLUT[i];
|
||||
if (name->IsEqualTo(CStrVector(entry->name))) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
CodeGenerator::InlineFunctionGenerator
|
||||
CodeGenerator::FindInlineFunctionGenerator(Runtime::FunctionId id) {
|
||||
return kInlineFunctionGenerators[
|
||||
static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction)];
|
||||
}
|
||||
|
||||
|
||||
bool CodeGenerator::CheckForInlineRuntimeCall(CallRuntime* node) {
|
||||
ZoneList<Expression*>* args = node->arguments();
|
||||
Handle<String> name = node->name();
|
||||
if (name->length() > 0 && name->Get(0) == '_') {
|
||||
InlineRuntimeLUT* entry = FindInlineRuntimeLUT(name);
|
||||
if (entry != NULL) {
|
||||
((*this).*(entry->method))(args);
|
||||
Runtime::Function* function = node->function();
|
||||
if (function != NULL && function->intrinsic_type == Runtime::INLINE) {
|
||||
InlineFunctionGenerator generator =
|
||||
FindInlineFunctionGenerator(function->function_id);
|
||||
if (generator != NULL) {
|
||||
((*this).*(generator))(args);
|
||||
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
|
||||
// known result for the test expression, with no side effects.
|
||||
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
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
@ -71,48 +71,6 @@
|
||||
// CodeForDoWhileConditionPosition
|
||||
// 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
|
||||
#include "ia32/codegen-ia32.h"
|
||||
#elif V8_TARGET_ARCH_X64
|
||||
|
@ -505,18 +505,36 @@ void FullCodeGenerator::SetSourcePosition(int pos) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) {
|
||||
Handle<String> name = expr->name();
|
||||
SmartPointer<char> cstring = name->ToCString();
|
||||
// Lookup table for code generators for special runtime calls which are
|
||||
// generated inline.
|
||||
#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \
|
||||
&FullCodeGenerator::Emit##Name,
|
||||
|
||||
#define CHECK_EMIT_INLINE_CALL(name, x, y) \
|
||||
if (strcmp("_"#name, *cstring) == 0) { \
|
||||
Emit##name(expr->arguments()); \
|
||||
return; \
|
||||
}
|
||||
INLINE_RUNTIME_FUNCTION_LIST(CHECK_EMIT_INLINE_CALL)
|
||||
#undef CHECK_EMIT_INLINE_CALL
|
||||
UNREACHABLE();
|
||||
const FullCodeGenerator::InlineFunctionGenerator
|
||||
FullCodeGenerator::kInlineFunctionGenerators[] = {
|
||||
INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
|
||||
INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
|
||||
};
|
||||
#undef INLINE_FUNCTION_GENERATOR_ADDRESS
|
||||
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
// 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
|
||||
// parameter slot.
|
||||
int SlotOffset(Slot* slot);
|
||||
@ -373,10 +379,13 @@ class FullCodeGenerator: public AstVisitor {
|
||||
void EmitKeyedCallWithIC(Call* expr, Expression* key, RelocInfo::Mode mode);
|
||||
|
||||
// Platform-specific code for inline runtime calls.
|
||||
InlineFunctionGenerator FindInlineFunctionGenerator(Runtime::FunctionId id);
|
||||
|
||||
void EmitInlineRuntimeCall(CallRuntime* expr);
|
||||
|
||||
#define EMIT_INLINE_RUNTIME_CALL(name, x, y) \
|
||||
void Emit##name(ZoneList<Expression*>* arguments);
|
||||
INLINE_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL)
|
||||
INLINE_RUNTIME_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL)
|
||||
#undef EMIT_INLINE_RUNTIME_CALL
|
||||
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include "api.h"
|
||||
#include "arguments.h"
|
||||
#include "bootstrapper.h"
|
||||
#include "codegen.h"
|
||||
#include "compiler.h"
|
||||
#include "debug.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
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
@ -1834,6 +1834,13 @@ bool Heap::CreateInitialObjects() {
|
||||
|
||||
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;
|
||||
|
||||
// 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
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
@ -114,6 +114,7 @@ namespace internal {
|
||||
V(Object, last_script_id, LastScriptId) \
|
||||
V(Script, empty_script, EmptyScript) \
|
||||
V(Smi, real_stack_limit, RealStackLimit) \
|
||||
V(StringDictionary, intrinsic_function_names, IntrinsicFunctionNames) \
|
||||
|
||||
#if V8_TARGET_ARCH_ARM && !V8_INTERPRETED_REGEXP
|
||||
#define STRONG_ROOT_LIST(V) \
|
||||
|
@ -345,10 +345,6 @@ class CodeGenerator: public AstVisitor {
|
||||
bool in_spilled_code() const { return in_spilled_code_; }
|
||||
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|
|
||||
// in FixedArray pointer to which is held in |array|. |index_as_smi| is Smi.
|
||||
static Operand FixedArrayElementOperand(Register array,
|
||||
@ -363,6 +359,12 @@ class CodeGenerator: public AstVisitor {
|
||||
}
|
||||
|
||||
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
|
||||
explicit CodeGenerator(MacroAssembler* masm);
|
||||
|
||||
@ -624,13 +626,9 @@ class CodeGenerator: public AstVisitor {
|
||||
|
||||
void CheckStack();
|
||||
|
||||
struct InlineRuntimeLUT {
|
||||
void (CodeGenerator::*method)(ZoneList<Expression*>*);
|
||||
const char* name;
|
||||
int nargs;
|
||||
};
|
||||
static InlineFunctionGenerator FindInlineFunctionGenerator(
|
||||
Runtime::FunctionId function_id);
|
||||
|
||||
static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
|
||||
bool CheckForInlineRuntimeCall(CallRuntime* node);
|
||||
|
||||
void ProcessDeclarations(ZoneList<Declaration*>* declarations);
|
||||
@ -792,8 +790,6 @@ class CodeGenerator: public AstVisitor {
|
||||
// in a spilled state.
|
||||
bool in_spilled_code_;
|
||||
|
||||
static InlineRuntimeLUT kInlineRuntimeLUT[];
|
||||
|
||||
friend class VirtualFrame;
|
||||
friend class JumpTarget;
|
||||
friend class Reference;
|
||||
|
@ -4243,58 +4243,43 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) {
|
||||
|
||||
Expect(Token::MOD, CHECK_OK);
|
||||
Handle<String> name = ParseIdentifier(CHECK_OK);
|
||||
Runtime::Function* function =
|
||||
Runtime::FunctionForName(scanner_.literal());
|
||||
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
|
||||
// very first time not when reparsing because of lazy compilation.
|
||||
top_scope_->ForceEagerCompilation();
|
||||
}
|
||||
|
||||
// Check for built-in macros.
|
||||
if (!is_pre_parsing_) {
|
||||
if (function == Runtime::FunctionForId(Runtime::kIS_VAR)) {
|
||||
// %IS_VAR(x)
|
||||
// evaluates to x if x is a variable,
|
||||
// leads to a parse error otherwise
|
||||
if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
|
||||
return args->at(0);
|
||||
}
|
||||
*ok = false;
|
||||
// Check here for other macros.
|
||||
// } else if (function == Runtime::FunctionForId(Runtime::kIS_VAR)) {
|
||||
// ...
|
||||
}
|
||||
Runtime::Function* function = Runtime::FunctionForSymbol(name);
|
||||
|
||||
if (!*ok) {
|
||||
// We found a macro but it failed.
|
||||
// Check for built-in IS_VAR macro.
|
||||
if (function != NULL &&
|
||||
function->intrinsic_type == Runtime::RUNTIME &&
|
||||
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) {
|
||||
return args->at(0);
|
||||
} else {
|
||||
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;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise we have a valid runtime call.
|
||||
// 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;
|
||||
}
|
||||
|
||||
// We have a valid intrinsics call or a call to a builtin.
|
||||
return NEW(CallRuntime(name, function, args));
|
||||
}
|
||||
|
||||
|
@ -4519,7 +4519,6 @@ static Object* Runtime_StringParseInt(Arguments args) {
|
||||
RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
|
||||
double value = StringToInt(s, radix);
|
||||
return Heap::NumberFromDouble(value);
|
||||
return Heap::nan_value();
|
||||
}
|
||||
|
||||
|
||||
@ -10064,6 +10063,7 @@ static Object* Runtime_ListNatives(Arguments args) {
|
||||
inline_runtime_functions = false;
|
||||
RUNTIME_FUNCTION_LIST(ADD_ENTRY)
|
||||
inline_runtime_functions = true;
|
||||
INLINE_FUNCTION_LIST(ADD_ENTRY)
|
||||
INLINE_RUNTIME_FUNCTION_LIST(ADD_ENTRY)
|
||||
#undef ADD_ENTRY
|
||||
return *result;
|
||||
@ -10090,35 +10090,58 @@ static Object* Runtime_IS_VAR(Arguments args) {
|
||||
// ----------------------------------------------------------------------------
|
||||
// Implementation of Runtime
|
||||
|
||||
#define F(name, nargs, ressize) \
|
||||
{ #name, FUNCTION_ADDR(Runtime_##name), nargs, \
|
||||
static_cast<int>(Runtime::k##name), ressize },
|
||||
#define F(name, number_of_args, result_size) \
|
||||
{ Runtime::k##name, Runtime::RUNTIME, #name, \
|
||||
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)
|
||||
{ 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) {
|
||||
ASSERT(0 <= fid && fid < kNofFunctions);
|
||||
return &Runtime_functions[fid];
|
||||
Object* Runtime::InitializeIntrinsicFunctionNames(Object* dictionary) {
|
||||
ASSERT(dictionary != NULL);
|
||||
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) {
|
||||
for (Function* f = Runtime_functions; f->name != NULL; f++) {
|
||||
if (strncmp(f->name, name.start(), name.length()) == 0
|
||||
&& f->name[name.length()] == 0) {
|
||||
return f;
|
||||
}
|
||||
Runtime::Function* Runtime::FunctionForSymbol(Handle<String> name) {
|
||||
int entry = Heap::intrinsic_function_names()->FindEntry(*name);
|
||||
if (entry != kNotFound) {
|
||||
Object* smi_index = Heap::intrinsic_function_names()->ValueAt(entry);
|
||||
int function_index = Smi::cast(smi_index)->value();
|
||||
return &(kIntrinsicFunctions[function_index]);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
|
||||
return &(kIntrinsicFunctions[static_cast<int>(id)]);
|
||||
}
|
||||
|
||||
|
||||
void Runtime::PerformGC(Object* result) {
|
||||
Failure* failure = Failure::cast(result);
|
||||
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
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
@ -389,6 +389,59 @@ namespace internal {
|
||||
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.
|
||||
|
||||
class Runtime : public AllStatic {
|
||||
@ -396,33 +449,52 @@ class Runtime : public AllStatic {
|
||||
enum FunctionId {
|
||||
#define F(name, nargs, ressize) k##name,
|
||||
RUNTIME_FUNCTION_LIST(F)
|
||||
kNofFunctions
|
||||
#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 {
|
||||
FunctionId function_id;
|
||||
IntrinsicType intrinsic_type;
|
||||
// The JS name of the function.
|
||||
const char* name;
|
||||
|
||||
// The C++ (native) entry point.
|
||||
// The C++ (native) entry point. NULL if the function is inlined.
|
||||
byte* entry;
|
||||
|
||||
// The number of arguments expected; nargs < 0 if variable no. of
|
||||
// arguments.
|
||||
// The number of arguments expected. nargs is -1 if the function takes
|
||||
// a variable number of arguments.
|
||||
int nargs;
|
||||
int stub_id;
|
||||
// Size of result, if complex (larger than a single pointer),
|
||||
// otherwise zero.
|
||||
// Size of result. Most functions return a single pointer, size 1.
|
||||
int result_size;
|
||||
};
|
||||
|
||||
// Get the runtime function with the given function id.
|
||||
static Function* FunctionForId(FunctionId fid);
|
||||
static const int kNotFound = -1;
|
||||
|
||||
// Get the runtime function with the given name.
|
||||
static Function* FunctionForName(Vector<const char> name);
|
||||
// Add symbols for all the intrinsic function names to a StringDictionary.
|
||||
// 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 bool IsUpperCaseChar(uint16_t ch);
|
||||
|
@ -343,15 +343,17 @@ class CodeGenerator: public AstVisitor {
|
||||
bool in_spilled_code() const { return in_spilled_code_; }
|
||||
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) {
|
||||
return Operand(context, Context::SlotOffset(index));
|
||||
}
|
||||
|
||||
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
|
||||
explicit CodeGenerator(MacroAssembler* masm);
|
||||
|
||||
@ -584,12 +586,9 @@ class CodeGenerator: public AstVisitor {
|
||||
|
||||
void CheckStack();
|
||||
|
||||
struct InlineRuntimeLUT {
|
||||
void (CodeGenerator::*method)(ZoneList<Expression*>*);
|
||||
const char* name;
|
||||
int nargs;
|
||||
};
|
||||
static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
|
||||
static InlineFunctionGenerator FindInlineFunctionGenerator(
|
||||
Runtime::FunctionId function_id);
|
||||
|
||||
bool CheckForInlineRuntimeCall(CallRuntime* node);
|
||||
|
||||
void ProcessDeclarations(ZoneList<Declaration*>* declarations);
|
||||
@ -742,8 +741,6 @@ class CodeGenerator: public AstVisitor {
|
||||
// in a spilled state.
|
||||
bool in_spilled_code_;
|
||||
|
||||
static InlineRuntimeLUT kInlineRuntimeLUT[];
|
||||
|
||||
friend class VirtualFrame;
|
||||
friend class JumpTarget;
|
||||
friend class Reference;
|
||||
|
Loading…
Reference in New Issue
Block a user