LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
- MathFunctionId op = instr->op();
+ BuiltinFunctionId op = instr->op();
LOperand* input = UseRegisterAtStart(instr->value());
LInstruction* result = new LUnaryMathOperation(input);
switch (op) {
DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
virtual void PrintDataTo(StringStream* stream) const;
- MathFunctionId op() const { return hydrogen()->op(); }
+ BuiltinFunctionId op() const { return hydrogen()->op(); }
};
// -- lr : return address
// -----------------------------------
SharedFunctionInfo* function_info = function->shared();
- if (function_info->HasCustomCallGenerator()) {
- const int id = function_info->custom_call_generator_id();
+ if (function_info->HasBuiltinFunctionId()) {
+ BuiltinFunctionId id = function_info->builtin_function_id();
MaybeObject* maybe_result = CompileCustomCall(
id, object, holder, NULL, function, name);
Object* result;
// -----------------------------------
SharedFunctionInfo* function_info = function->shared();
- if (function_info->HasCustomCallGenerator()) {
- const int id = function_info->custom_call_generator_id();
+ if (function_info->HasBuiltinFunctionId()) {
+ BuiltinFunctionId id = function_info->builtin_function_id();
MaybeObject* maybe_result = CompileCustomCall(
id, object, holder, cell, function, name);
Object* result;
#include "parser.h"
#include "scopes.h"
#include "string-stream.h"
+#include "stub-cache.h"
namespace v8 {
namespace internal {
static bool CallWithoutIC(Handle<JSFunction> target, int arity) {
+ SharedFunctionInfo* info = target->shared();
if (target->NeedsArgumentsAdaption()) {
// If the number of formal parameters of the target function
// does not match the number of arguments we're passing, we
// don't want to deal with it.
- return target->shared()->formal_parameter_count() == arity;
+ return info->formal_parameter_count() == arity;
} else {
// If the target doesn't need arguments adaption, we can call
// it directly, but we avoid to do so if it has a custom call
// generator, because that is likely to generate better code.
- return !target->shared()->HasCustomCallGenerator();
+ return !info->HasBuiltinFunctionId() ||
+ !CallStubCompiler::HasCustomCallGenerator(info->builtin_function_id());
}
}
#include "natives.h"
#include "objects-visiting.h"
#include "snapshot.h"
-#include "stub-cache.h"
#include "extensions/externalize-string-extension.h"
#include "extensions/gc-extension.h"
// Used for creating a context from scratch.
void InstallNativeFunctions();
bool InstallNatives();
- void InstallCustomCallGenerators();
+ void InstallBuiltinFunctionIds();
void InstallJSFunctionResultCaches();
void InitializeNormalizedMapCaches();
// Used both for deserialized and from-scratch contexts to add the extensions
global_context()->set_string_function_prototype_map(
HeapObject::cast(string_function->initial_map()->prototype())->map());
- InstallCustomCallGenerators();
+ InstallBuiltinFunctionIds();
// Install Function.prototype.call and apply.
{ Handle<String> key = Factory::function_class_symbol();
}
-static Handle<JSObject> ResolveCustomCallGeneratorHolder(
+static Handle<JSObject> ResolveBuiltinIdHolder(
Handle<Context> global_context,
const char* holder_expr) {
Handle<GlobalObject> global(global_context->global());
}
-static void InstallCustomCallGenerator(Handle<JSObject> holder,
- const char* function_name,
- int id) {
+static void InstallBuiltinFunctionId(Handle<JSObject> holder,
+ const char* function_name,
+ BuiltinFunctionId id) {
Handle<String> name = Factory::LookupAsciiSymbol(function_name);
Object* function_object = holder->GetProperty(*name)->ToObjectUnchecked();
Handle<JSFunction> function(JSFunction::cast(function_object));
}
-void Genesis::InstallCustomCallGenerators() {
+void Genesis::InstallBuiltinFunctionIds() {
HandleScope scope;
-#define INSTALL_CALL_GENERATOR(holder_expr, fun_name, name) \
- { \
- Handle<JSObject> holder = ResolveCustomCallGeneratorHolder( \
- global_context(), #holder_expr); \
- const int id = CallStubCompiler::k##name##CallGenerator; \
- InstallCustomCallGenerator(holder, #fun_name, id); \
+#define INSTALL_BUILTIN_ID(holder_expr, fun_name, name) \
+ { \
+ Handle<JSObject> holder = ResolveBuiltinIdHolder( \
+ global_context(), #holder_expr); \
+ BuiltinFunctionId id = k##name; \
+ InstallBuiltinFunctionId(holder, #fun_name, id); \
}
- CUSTOM_CALL_IC_GENERATORS(INSTALL_CALL_GENERATOR)
-#undef INSTALL_CALL_GENERATOR
+ FUNCTIONS_WITH_ID_LIST(INSTALL_BUILTIN_ID)
+#undef INSTALL_BUILTIN_ID
}
class HUnaryMathOperation: public HUnaryOperation {
public:
- HUnaryMathOperation(HValue* value, MathFunctionId op)
+ HUnaryMathOperation(HValue* value, BuiltinFunctionId op)
: HUnaryOperation(value), op_(op) {
switch (op) {
case kMathFloor:
case kMathSqrt:
case kMathPowHalf:
case kMathLog:
- default:
set_representation(Representation::Double());
+ break;
+ default:
+ UNREACHABLE();
}
SetFlag(kUseGVN);
}
return this;
}
- MathFunctionId op() const { return op_; }
+ BuiltinFunctionId op() const { return op_; }
const char* OpName() const;
DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation, "unary_math_operation")
private:
- MathFunctionId op_;
+ BuiltinFunctionId op_;
};
bool HGraphBuilder::TryMathFunctionInline(Call* expr) {
// Try to inline calls like Math.* as operations in the calling function.
- MathFunctionId id = expr->target()->shared()->math_function_id();
+ if (!expr->target()->shared()->IsBuiltinMathFunction()) return false;
+ BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
int argument_count = expr->arguments()->length() + 1; // Plus receiver.
switch (id) {
case kMathRound:
}
break;
default:
- // Either not a special math function or not yet supported for inlining.
+ // Not yet supported for inlining.
break;
}
return false;
LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
- MathFunctionId op = instr->op();
+ BuiltinFunctionId op = instr->op();
if (op == kMathLog) {
LOperand* input = UseFixedDouble(instr->value(), xmm1);
LInstruction* result = new LUnaryMathOperation(input);
DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
virtual void PrintDataTo(StringStream* stream) const;
- MathFunctionId op() const { return hydrogen()->op(); }
+ BuiltinFunctionId op() const { return hydrogen()->op(); }
};
// -----------------------------------
SharedFunctionInfo* function_info = function->shared();
- if (function_info->HasCustomCallGenerator()) {
- const int id = function_info->custom_call_generator_id();
+ if (function_info->HasBuiltinFunctionId()) {
+ BuiltinFunctionId id = function_info->builtin_function_id();
MaybeObject* maybe_result = CompileCustomCall(
id, object, holder, NULL, function, name);
Object* result;
// -----------------------------------
SharedFunctionInfo* function_info = function->shared();
- if (function_info->HasCustomCallGenerator()) {
- const int id = function_info->custom_call_generator_id();
+ if (function_info->HasBuiltinFunctionId()) {
+ BuiltinFunctionId id = function_info->builtin_function_id();
MaybeObject* maybe_result = CompileCustomCall(
id, object, holder, cell, function, name);
Object* result;
"max", MathMax,
"min", MathMin
));
-
- // The values here are from the MathFunctionId enum in objects.h.
- %SetMathFunctionId($Math.floor, 1);
- %SetMathFunctionId($Math.round, 2);
- %SetMathFunctionId($Math.abs, 4);
- %SetMathFunctionId($Math.sqrt, 0xd);
- %SetMathFunctionId($Math.pow, 0xe);
- %SetMathFunctionId($Math.log, 5);
- // TODO(erikcorry): Set the id of the other functions so they can be
- // optimized.
};
}
-bool SharedFunctionInfo::HasCustomCallGenerator() {
+bool SharedFunctionInfo::HasBuiltinFunctionId() {
return function_data()->IsSmi();
}
-MathFunctionId SharedFunctionInfo::math_function_id() {
- return static_cast<MathFunctionId>(
- (compiler_hints() >> kMathFunctionShift) & kMathFunctionMask);
+bool SharedFunctionInfo::IsBuiltinMathFunction() {
+ return HasBuiltinFunctionId() &&
+ builtin_function_id() >= kFirstMathFunctionId;
}
-void SharedFunctionInfo::set_math_function_id(int math_fn) {
- ASSERT(math_fn <= max_math_id_number());
- set_compiler_hints(compiler_hints() |
- ((math_fn & kMathFunctionMask) << kMathFunctionShift));
-}
-
-
-int SharedFunctionInfo::custom_call_generator_id() {
- ASSERT(HasCustomCallGenerator());
- return Smi::cast(function_data())->value();
+BuiltinFunctionId SharedFunctionInfo::builtin_function_id() {
+ ASSERT(HasBuiltinFunctionId());
+ return static_cast<BuiltinFunctionId>(Smi::cast(function_data())->value());
}
};
-enum MathFunctionId {
- kNotSpecialMathFunction = 0,
- // These numbers must be kept in sync with the ones in math.js.
- kMathFloor = 1,
- kMathRound = 2,
- kMathCeil = 3,
- kMathAbs = 4,
- kMathLog = 5,
- kMathSin = 6,
- kMathCos = 7,
- kMathTan = 8,
- kMathASin = 9,
- kMathACos = 0xa,
- kMathATan = 0xb,
- kMathExp = 0xc,
- kMathSqrt = 0xd,
- kMathPow = 0xe,
- kMathPowHalf = 0xf
+// List of builtin functions we want to identify to improve code
+// generation.
+//
+// Each entry has a name of a global object property holding an object
+// optionally followed by ".prototype", a name of a builtin function
+// on the object (the one the id is set for), and a label.
+//
+// Installation of ids for the selected builtin functions is handled
+// by the bootstrapper.
+//
+// NOTE: Order is important: math functions should be at the end of
+// the list and MathFloor should be the first math function.
+#define FUNCTIONS_WITH_ID_LIST(V) \
+ V(Array.prototype, push, ArrayPush) \
+ V(Array.prototype, pop, ArrayPop) \
+ V(String.prototype, charCodeAt, StringCharCodeAt) \
+ V(String.prototype, charAt, StringCharAt) \
+ V(String, fromCharCode, StringFromCharCode) \
+ V(Math, floor, MathFloor) \
+ V(Math, round, MathRound) \
+ V(Math, ceil, MathCeil) \
+ V(Math, abs, MathAbs) \
+ V(Math, log, MathLog) \
+ V(Math, sin, MathSin) \
+ V(Math, cos, MathCos) \
+ V(Math, tan, MathTan) \
+ V(Math, asin, MathASin) \
+ V(Math, acos, MathACos) \
+ V(Math, atan, MathATan) \
+ V(Math, exp, MathExp) \
+ V(Math, sqrt, MathSqrt) \
+ V(Math, pow, MathPow)
+
+
+enum BuiltinFunctionId {
+#define DECLARE_FUNCTION_ID(ignored1, ignore2, name) \
+ k##name,
+ FUNCTIONS_WITH_ID_LIST(DECLARE_FUNCTION_ID)
+#undef DECLARE_FUNCTION_ID
+ // Fake id for a special case of Math.pow. Note, it continues the
+ // list of math functions.
+ kMathPowHalf,
+ kFirstMathFunctionId = kMathFloor
};
// [function data]: This field holds some additional data for function.
// Currently it either has FunctionTemplateInfo to make benefit the API
- // or Smi identifying a custom call generator.
+ // or Smi identifying a builtin function.
// In the long run we don't want all functions to have this field but
// we can fix that when we have a better model for storing hidden data
// on objects.
inline bool IsApiFunction();
inline FunctionTemplateInfo* get_api_func_data();
- inline bool HasCustomCallGenerator();
- inline int custom_call_generator_id();
+ inline bool HasBuiltinFunctionId();
+ inline bool IsBuiltinMathFunction();
+ inline BuiltinFunctionId builtin_function_id();
// [script info]: Script from which the function originates.
DECL_ACCESSORS(script, Object)
static const int kAlignedSize = POINTER_SIZE_ALIGN(kSize);
- // Get/set a special tag on the functions from math.js so we can inline
- // efficient versions of them in the code.
- inline MathFunctionId math_function_id();
- inline void set_math_function_id(int id);
- static inline int max_math_id_number() { return kMathFunctionMask; }
-
typedef FixedBodyDescriptor<kNameOffset,
kThisPropertyAssignmentsOffset + kPointerSize,
kSize> BodyDescriptor;
static const int kHasOnlySimpleThisPropertyAssignments = 0;
static const int kTryFullCodegen = 1;
static const int kAllowLazyCompilation = 2;
- static const int kMathFunctionShift = 3;
- static const int kMathFunctionMask = 0x1f;
- static const int kLiveObjectsMayExist = 8;
- static const int kCodeAgeShift = 9;
+ static const int kLiveObjectsMayExist = 3;
+ static const int kCodeAgeShift = 4;
static const int kCodeAgeMask = 0x7;
- static const int kOptimizationDisabled = 12;
+ static const int kOptimizationDisabled = 7;
DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo);
};
}
-// Sets the magic number that identifies a function as one of the special
-// math functions that can be inlined.
-static MaybeObject* Runtime_SetMathFunctionId(Arguments args) {
- NoHandleAllocation ha;
- ASSERT(args.length() == 2);
- CONVERT_CHECKED(JSFunction, function, args[0]);
- CONVERT_CHECKED(Smi, id, args[1]);
- RUNTIME_ASSERT(id->value() >= 0);
- RUNTIME_ASSERT(id->value() < SharedFunctionInfo::max_math_id_number());
-
- function->shared()->set_math_function_id(id->value());
-
- return Heap::undefined_value();
-}
-
-
static MaybeObject* Runtime_IsConstructCall(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 0);
\
F(IsInPrototypeChain, 2, 1) \
F(SetHiddenPrototype, 2, 1) \
- F(SetMathFunctionId, 2, 1) \
\
F(IsConstructCall, 0, 1) \
\
}
-MaybeObject* CallStubCompiler::CompileCustomCall(int generator_id,
+bool CallStubCompiler::HasCustomCallGenerator(BuiltinFunctionId id) {
+#define CALL_GENERATOR_CASE(name) if (id == k##name) return true;
+ CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
+#undef CALL_GENERATOR_CASE
+ return false;
+}
+
+
+MaybeObject* CallStubCompiler::CompileCustomCall(BuiltinFunctionId id,
Object* object,
JSObject* holder,
JSGlobalPropertyCell* cell,
JSFunction* function,
String* fname) {
- ASSERT(generator_id >= 0 && generator_id < kNumCallGenerators);
- switch (generator_id) {
-#define CALL_GENERATOR_CASE(ignored1, ignored2, name) \
- case k##name##CallGenerator: \
- return CallStubCompiler::Compile##name##Call(object, \
- holder, \
- cell, \
- function, \
- fname);
- CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
+#define CALL_GENERATOR_CASE(name) \
+ if (id == k##name) { \
+ return CallStubCompiler::Compile##name##Call(object, \
+ holder, \
+ cell, \
+ function, \
+ fname); \
+ }
+ CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
#undef CALL_GENERATOR_CASE
- }
- UNREACHABLE();
+ ASSERT(!HasCustomCallGenerator(id));
return Heap::undefined_value();
}
};
-// List of functions with custom constant call IC stubs.
-//
-// Installation of custom call generators for the selected builtins is
-// handled by the bootstrapper.
-//
-// Each entry has a name of a global object property holding an object
-// optionally followed by ".prototype" (this controls whether the
-// generator is set on the object itself or, in case it's a function,
-// on the its instance prototype), a name of a builtin function on the
-// object (the one the generator is set for), and a name of the
-// generator (used to build ids and generator function names).
-#define CUSTOM_CALL_IC_GENERATORS(V) \
- V(Array.prototype, push, ArrayPush) \
- V(Array.prototype, pop, ArrayPop) \
- V(String.prototype, charCodeAt, StringCharCodeAt) \
- V(String.prototype, charAt, StringCharAt) \
- V(String, fromCharCode, StringFromCharCode) \
- V(Math, floor, MathFloor) \
- V(Math, abs, MathAbs)
+// Subset of FUNCTIONS_WITH_ID_LIST with custom constant/global call
+// IC stubs.
+#define CUSTOM_CALL_IC_GENERATORS(V) \
+ V(ArrayPush) \
+ V(ArrayPop) \
+ V(StringCharCodeAt) \
+ V(StringCharAt) \
+ V(StringFromCharCode) \
+ V(MathFloor) \
+ V(MathAbs)
class CallStubCompiler: public StubCompiler {
public:
- enum {
-#define DECLARE_CALL_GENERATOR_ID(ignored1, ignore2, name) \
- k##name##CallGenerator,
- CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR_ID)
-#undef DECLARE_CALL_GENERATOR_ID
- kNumCallGenerators
- };
-
CallStubCompiler(int argc,
InLoopFlag in_loop,
Code::Kind kind,
JSFunction* function,
String* name);
- // Compiles a custom call constant/global IC using the generator
- // with given id. For constant calls cell is NULL.
- MUST_USE_RESULT MaybeObject* CompileCustomCall(int generator_id,
+ static bool HasCustomCallGenerator(BuiltinFunctionId id);
+
+ private:
+ // Compiles a custom call constant/global IC. For constant calls
+ // cell is NULL. Returns undefined if there is no custom call code
+ // for the given function or it can't be generated.
+ MUST_USE_RESULT MaybeObject* CompileCustomCall(BuiltinFunctionId id,
Object* object,
JSObject* holder,
JSGlobalPropertyCell* cell,
JSFunction* function,
String* name);
-#define DECLARE_CALL_GENERATOR(ignored1, ignored2, name) \
+#define DECLARE_CALL_GENERATOR(name) \
MUST_USE_RESULT MaybeObject* Compile##name##Call(Object* object, \
JSObject* holder, \
JSGlobalPropertyCell* cell, \
CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
#undef DECLARE_CALL_GENERATOR
- private:
const ParameterCount arguments_;
const InLoopFlag in_loop_;
const Code::Kind kind_;
// -----------------------------------
SharedFunctionInfo* function_info = function->shared();
- if (function_info->HasCustomCallGenerator()) {
- const int id = function_info->custom_call_generator_id();
+ if (function_info->HasBuiltinFunctionId()) {
+ BuiltinFunctionId id = function_info->builtin_function_id();
MaybeObject* maybe_result = CompileCustomCall(
id, object, holder, NULL, function, name);
Object* result;
// -----------------------------------
SharedFunctionInfo* function_info = function->shared();
- if (function_info->HasCustomCallGenerator()) {
- const int id = function_info->custom_call_generator_id();
+ if (function_info->HasBuiltinFunctionId()) {
+ BuiltinFunctionId id = function_info->builtin_function_id();
MaybeObject* maybe_result = CompileCustomCall(
id, object, holder, cell, function, name);
Object* result;