From fc83faa8fd0996977d08a0773aff299660524cd8 Mon Sep 17 00:00:00 2001 From: "whesse@chromium.org" Date: Tue, 14 Sep 2010 14:52:53 +0000 Subject: [PATCH] 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 --- src/arm/codegen-arm.h | 20 ++++----- src/codegen.cc | 53 +++++++++------------- src/codegen.h | 44 +----------------- src/full-codegen.cc | 40 ++++++++++++----- src/full-codegen.h | 9 ++++ src/handles.cc | 1 - src/heap.cc | 9 +++- src/heap.h | 3 +- src/ia32/codegen-ia32.h | 20 ++++----- src/parser.cc | 63 ++++++++++---------------- src/runtime.cc | 55 ++++++++++++++++------- src/runtime.h | 98 +++++++++++++++++++++++++++++++++++------ src/x64/codegen-x64.h | 21 ++++----- 13 files changed, 242 insertions(+), 194 deletions(-) diff --git a/src/arm/codegen-arm.h b/src/arm/codegen-arm.h index 162d97fd98..d4c352260e 100644 --- a/src/arm/codegen-arm.h +++ b/src/arm/codegen-arm.h @@ -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 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*); + + 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*); - const char* name; - int nargs; - }; + static InlineFunctionGenerator FindInlineFunctionGenerator( + Runtime::FunctionId function_id); - static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle name); bool CheckForInlineRuntimeCall(CallRuntime* node); static Handle 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; diff --git a/src/codegen.cc b/src/codegen.cc index 148cefca40..daf1c0db61 100644 --- a/src/codegen.cc +++ b/src/codegen.cc @@ -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 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(id) - static_cast(Runtime::kFirstInlineFunction)]; } bool CodeGenerator::CheckForInlineRuntimeCall(CallRuntime* node) { ZoneList* args = node->arguments(); Handle 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 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( diff --git a/src/codegen.h b/src/codegen.h index aa2d4422c3..2a4d9d4ccb 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -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 diff --git a/src/full-codegen.cc b/src/full-codegen.cc index 7de4a0069c..5fff139214 100644 --- a/src/full-codegen.cc +++ b/src/full-codegen.cc @@ -505,18 +505,36 @@ void FullCodeGenerator::SetSourcePosition(int pos) { } -void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) { - Handle name = expr->name(); - SmartPointer 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(id) - static_cast(Runtime::kFirstInlineFunction)]; +} + + +void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* node) { + ZoneList* args = node->arguments(); + Handle 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); } diff --git a/src/full-codegen.h b/src/full-codegen.h index ab0fd36c0d..9db233c229 100644 --- a/src/full-codegen.h +++ b/src/full-codegen.h @@ -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*); + + 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* arguments); + INLINE_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL) INLINE_RUNTIME_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL) #undef EMIT_INLINE_RUNTIME_CALL diff --git a/src/handles.cc b/src/handles.cc index 01464016be..655254c95d 100644 --- a/src/handles.cc +++ b/src/handles.cc @@ -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" diff --git a/src/heap.cc b/src/heap.cc index 443c926d95..8c61f33f1e 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -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. diff --git a/src/heap.h b/src/heap.h index 484cd22bdf..6bcac9f7e0 100644 --- a/src/heap.h +++ b/src/heap.h @@ -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) \ diff --git a/src/ia32/codegen-ia32.h b/src/ia32/codegen-ia32.h index adc00058df..c4a03d1109 100644 --- a/src/ia32/codegen-ia32.h +++ b/src/ia32/codegen-ia32.h @@ -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 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*); + + 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*); - const char* name; - int nargs; - }; + static InlineFunctionGenerator FindInlineFunctionGenerator( + Runtime::FunctionId function_id); - static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle name); bool CheckForInlineRuntimeCall(CallRuntime* node); void ProcessDeclarations(ZoneList* 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; diff --git a/src/parser.cc b/src/parser.cc index 11e2eb559e..d41eb81ac6 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -4243,58 +4243,43 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) { Expect(Token::MOD, CHECK_OK); Handle name = ParseIdentifier(CHECK_OK); - Runtime::Function* function = - Runtime::FunctionForName(scanner_.literal()); ZoneList* 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::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::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::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::empty()); + *ok = false; + return NULL; + } + + // We have a valid intrinsics call or a call to a builtin. return NEW(CallRuntime(name, function, args)); } diff --git a/src/runtime.cc b/src/runtime.cc index a1f6810317..a8a51d9b2f 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -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(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 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 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(id)]); +} + + void Runtime::PerformGC(Object* result) { Failure* failure = Failure::cast(result); if (failure->IsRetryAfterGC()) { diff --git a/src/runtime.h b/src/runtime.h index 312907adc5..8a3671a540 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -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 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 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 sub, Handle pat, int index); static bool IsUpperCaseChar(uint16_t ch); diff --git a/src/x64/codegen-x64.h b/src/x64/codegen-x64.h index 07bdadf9a1..6e1dd727ee 100644 --- a/src/x64/codegen-x64.h +++ b/src/x64/codegen-x64.h @@ -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 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*); + + 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*); - const char* name; - int nargs; - }; - static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle name); + static InlineFunctionGenerator FindInlineFunctionGenerator( + Runtime::FunctionId function_id); + bool CheckForInlineRuntimeCall(CallRuntime* node); void ProcessDeclarations(ZoneList* 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;