}
-void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) {
+void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) {
VirtualFrame::SpilledScope spilled_scope;
ASSERT(args->length() == 1);
static const int kUnknownIntValue = -1;
+ // If the name is an inline runtime function call return the number of
+ // expected arguments. Otherwise return -1.
+ static int InlineRuntimeCallArgumentsCount(Handle<String> name);
+
private:
// Construction/Destruction
explicit CodeGenerator(MacroAssembler* masm);
struct InlineRuntimeLUT {
void (CodeGenerator::*method)(ZoneList<Expression*>*);
const char* name;
+ int nargs;
};
static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
// Support for arguments.length and arguments[?].
void GenerateArgumentsLength(ZoneList<Expression*>* args);
- void GenerateArgumentsAccess(ZoneList<Expression*>* args);
+ void GenerateArguments(ZoneList<Expression*>* args);
// Support for accessing the class and value fields of an object.
void GenerateClassOf(ZoneList<Expression*>* args);
// Fast support for number to string.
void GenerateNumberToString(ZoneList<Expression*>* args);
- // Fast support for Math.pow().
+ // Fast call to math functions.
void GenerateMathPow(ZoneList<Expression*>* args);
-
- // Fast call to sine function.
void GenerateMathSin(ZoneList<Expression*>* args);
void GenerateMathCos(ZoneList<Expression*>* args);
-
- // Fast support for Math.pow().
void GenerateMathSqrt(ZoneList<Expression*>* args);
// Simple condition analysis.
}
+// 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.
+
+#define INLINE_RUNTIME_ENTRY(Name, argc, ressize) \
+ {&CodeGenerator::Generate##Name, "_" #Name, argc}, \
-// Special cases: These 'runtime calls' manipulate the current
-// frame and are only used 1 or two places, so we generate them
-// inline instead of generating calls to them. They are used
-// for implementing Function.prototype.call() and
-// Function.prototype.apply().
CodeGenerator::InlineRuntimeLUT CodeGenerator::kInlineRuntimeLUT[] = {
- {&CodeGenerator::GenerateIsSmi, "_IsSmi"},
- {&CodeGenerator::GenerateIsNonNegativeSmi, "_IsNonNegativeSmi"},
- {&CodeGenerator::GenerateIsArray, "_IsArray"},
- {&CodeGenerator::GenerateIsRegExp, "_IsRegExp"},
- {&CodeGenerator::GenerateIsConstructCall, "_IsConstructCall"},
- {&CodeGenerator::GenerateArgumentsLength, "_ArgumentsLength"},
- {&CodeGenerator::GenerateArgumentsAccess, "_Arguments"},
- {&CodeGenerator::GenerateClassOf, "_ClassOf"},
- {&CodeGenerator::GenerateValueOf, "_ValueOf"},
- {&CodeGenerator::GenerateSetValueOf, "_SetValueOf"},
- {&CodeGenerator::GenerateFastCharCodeAt, "_FastCharCodeAt"},
- {&CodeGenerator::GenerateCharFromCode, "_CharFromCode"},
- {&CodeGenerator::GenerateObjectEquals, "_ObjectEquals"},
- {&CodeGenerator::GenerateLog, "_Log"},
- {&CodeGenerator::GenerateRandomPositiveSmi, "_RandomPositiveSmi"},
- {&CodeGenerator::GenerateIsObject, "_IsObject"},
- {&CodeGenerator::GenerateIsFunction, "_IsFunction"},
- {&CodeGenerator::GenerateIsUndetectableObject, "_IsUndetectableObject"},
- {&CodeGenerator::GenerateStringAdd, "_StringAdd"},
- {&CodeGenerator::GenerateSubString, "_SubString"},
- {&CodeGenerator::GenerateStringCompare, "_StringCompare"},
- {&CodeGenerator::GenerateRegExpExec, "_RegExpExec"},
- {&CodeGenerator::GenerateNumberToString, "_NumberToString"},
- {&CodeGenerator::GenerateMathPow, "_Math_pow"},
- {&CodeGenerator::GenerateMathSin, "_Math_sin"},
- {&CodeGenerator::GenerateMathCos, "_Math_cos"},
- {&CodeGenerator::GenerateMathSqrt, "_Math_sqrt"},
+ INLINE_RUNTIME_FUNCTION_LIST(INLINE_RUNTIME_ENTRY)
};
+#undef INLINE_RUNTIME_ENTRY
CodeGenerator::InlineRuntimeLUT* CodeGenerator::FindInlineRuntimeLUT(
Handle<String> name) {
}
+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(
namespace internal {
+#define INLINE_RUNTIME_FUNCTION_LIST(F) \
+ F(IsSmi, 1, 1) \
+ F(IsNonNegativeSmi, 1, 1) \
+ F(IsArray, 1, 1) \
+ F(IsRegExp, 1, 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(FastCharCodeAt, 2, 1) \
+ F(CharFromCode, 1, 1) \
+ F(ObjectEquals, 2, 1) \
+ F(Log, 3, 1) \
+ F(RandomPositiveSmi, 0, 1) \
+ F(IsObject, 1, 1) \
+ F(IsFunction, 1, 1) \
+ F(IsUndetectableObject, 1, 1) \
+ F(StringAdd, 2, 1) \
+ F(SubString, 3, 1) \
+ F(StringCompare, 2, 1) \
+ F(RegExpExec, 4, 1) \
+ F(NumberToString, 1, 1) \
+ F(MathPow, 2, 1) \
+ F(MathSin, 1, 1) \
+ F(MathCos, 1, 1) \
+ F(MathSqrt, 1, 1)
+
+
// Support for "structured" code comments.
#ifdef DEBUG
}
-void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) {
+void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
// ArgumentsAccessStub expects the key in edx and the formal
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);
+
private:
// Construction/Destruction
explicit CodeGenerator(MacroAssembler* masm);
struct InlineRuntimeLUT {
void (CodeGenerator::*method)(ZoneList<Expression*>*);
const char* name;
+ int nargs;
};
static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
// Support for arguments.length and arguments[?].
void GenerateArgumentsLength(ZoneList<Expression*>* args);
- void GenerateArgumentsAccess(ZoneList<Expression*>* args);
+ void GenerateArguments(ZoneList<Expression*>* args);
// Support for accessing the class and value fields of an object.
void GenerateClassOf(ZoneList<Expression*>* args);
// Fast support for number to string.
void GenerateNumberToString(ZoneList<Expression*>* args);
- // Fast support for Math.pow().
+ // Fast call to math functions.
void GenerateMathPow(ZoneList<Expression*>* args);
-
- // Fast call to transcendental functions.
void GenerateMathSin(ZoneList<Expression*>* args);
void GenerateMathCos(ZoneList<Expression*>* args);
-
- // Fast case for sqrt
void GenerateMathSqrt(ZoneList<Expression*>* args);
// Simple condition analysis.
-// Copyright 2006-2008 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:
// ECMA 262 - 15.8.2.7
function MathCos(x) {
if (!IS_NUMBER(x)) x = ToNumber(x);
- return %_Math_cos(x);
+ return %_MathCos(x);
}
// ECMA 262 - 15.8.2.8
function MathPow(x, y) {
if (!IS_NUMBER(x)) x = ToNumber(x);
if (!IS_NUMBER(y)) y = ToNumber(y);
- return %_Math_pow(x, y);
+ return %_MathPow(x, y);
}
// ECMA 262 - 15.8.2.14
// ECMA 262 - 15.8.2.16
function MathSin(x) {
if (!IS_NUMBER(x)) x = ToNumber(x);
- return %_Math_sin(x);
+ return %_MathSin(x);
}
// ECMA 262 - 15.8.2.17
function MathSqrt(x) {
if (!IS_NUMBER(x)) x = ToNumber(x);
- return %_Math_sqrt(x);
+ return %_MathSqrt(x);
}
// ECMA 262 - 15.8.2.18
invalid_json: "String '%0' is not valid JSON",
circular_structure: "Converting circular structure to JSON",
obj_ctor_property_non_object: "Object.%0 called on non-object",
- array_indexof_not_defined: "Array.getIndexOf: Argument undefined"
+ array_indexof_not_defined: "Array.getIndexOf: Argument undefined",
+ illegal_access: "illegal access"
};
}
var format = kMessages[message.type];
#include "api.h"
#include "ast.h"
#include "bootstrapper.h"
+#include "codegen.h"
#include "compiler.h"
#include "messages.h"
#include "platform.h"
}
}
- // Otherwise we have a runtime call.
+ // 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.
return NEW(CallRuntime(name, function, args));
}
#include "accessors.h"
#include "api.h"
#include "arguments.h"
+#include "codegen.h"
#include "compiler.h"
#include "cpu.h"
#include "dateparser-inl.h"
HandleScope scope;
Handle<JSArray> result = Factory::NewJSArray(0);
int index = 0;
+ bool inline_runtime_functions = false;
#define ADD_ENTRY(Name, argc, ressize) \
{ \
HandleScope inner; \
- Handle<String> name = \
- Factory::NewStringFromAscii( \
- Vector<const char>(#Name, StrLength(#Name))); \
+ Handle<String> name; \
+ /* Inline runtime functions have an underscore in front of the name. */ \
+ if (inline_runtime_functions) { \
+ name = Factory::NewStringFromAscii( \
+ Vector<const char>("_" #Name, StrLength("_" #Name))); \
+ } else { \
+ name = Factory::NewStringFromAscii( \
+ Vector<const char>(#Name, StrLength(#Name))); \
+ } \
Handle<JSArray> pair = Factory::NewJSArray(0); \
SetElement(pair, 0, name); \
SetElement(pair, 1, Handle<Smi>(Smi::FromInt(argc))); \
SetElement(result, index++, pair); \
}
+ inline_runtime_functions = false;
RUNTIME_FUNCTION_LIST(ADD_ENTRY)
+ inline_runtime_functions = true;
+ INLINE_RUNTIME_FUNCTION_LIST(ADD_ENTRY)
#undef ADD_ENTRY
return *result;
}
}
-void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) {
+void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
// ArgumentsAccessStub expects the key in rdx and the formal
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);
+
private:
// Construction/Destruction
explicit CodeGenerator(MacroAssembler* masm);
struct InlineRuntimeLUT {
void (CodeGenerator::*method)(ZoneList<Expression*>*);
const char* name;
+ int nargs;
};
static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
bool CheckForInlineRuntimeCall(CallRuntime* node);
// Support for arguments.length and arguments[?].
void GenerateArgumentsLength(ZoneList<Expression*>* args);
- void GenerateArgumentsAccess(ZoneList<Expression*>* args);
+ void GenerateArguments(ZoneList<Expression*>* args);
// Support for accessing the class and value fields of an object.
void GenerateClassOf(ZoneList<Expression*>* args);
// Fast support for number to string.
void GenerateNumberToString(ZoneList<Expression*>* args);
- // Fast support for Math.pow().
- void GenerateMathPow(ZoneList<Expression*>* args);
-
// Fast call to math functions.
+ void GenerateMathPow(ZoneList<Expression*>* args);
void GenerateMathSin(ZoneList<Expression*>* args);
void GenerateMathCos(ZoneList<Expression*>* args);
-
- // Fast case for sqrt
void GenerateMathSqrt(ZoneList<Expression*>* args);
// Simple condition analysis.
public:
CodeGeneratorPatcher() {
CodeGenerator::InlineRuntimeLUT genGetFramePointer =
- {&CodeGenerator::GenerateGetFramePointer, "_GetFramePointer"};
- // _FastCharCodeAt is not used in our tests.
+ {&CodeGenerator::GenerateGetFramePointer, "_GetFramePointer", 0};
+ // _RandomPositiveSmi is not used in our tests. The one we replace need to
+ // have the same noumer of arguments as the one we put in, which is zero in
+ // this case.
bool result = CodeGenerator::PatchInlineRuntimeEntry(
- NewString("_FastCharCodeAt"),
+ NewString("_RandomPositiveSmi"),
genGetFramePointer, &oldInlineEntry);
CHECK(result);
}
return new Function(args.join(", "), "return %" + name + "(" + argsStr + ");");
}
-function testArgumentCount(name) {
+function testArgumentCount(name, argc) {
for (var i = 0; i < 10; i++) {
- var func = makeFunction(name, i);
+ var func = null;
+ try {
+ func = makeFunction(name, i);
+ } catch (e) {
+ if (e != "SyntaxError: illegal access") throw e;
+ }
+ if (func === null && i == argc) {
+ throw "unexpected exception";
+ }
var args = [ ];
for (var j = 0; j < i; j++)
args.push(0);
continue;
print(name);
var argc = nativeInfo[1];
- testArgumentCount(name);
+ testArgumentCount(name, argc);
testArgumentTypes(name, argc);
}
}