mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 878488: Implement asm.js Math constants; r=luke
This commit is contained in:
parent
09a620fea7
commit
7564359d12
@ -98,3 +98,4 @@ assertEq(asmLink(asmCompileCached("g","ffis", USE_ASM + "var x=ffis.x|0; functio
|
|||||||
var i32 = new Int32Array(4096);
|
var i32 = new Int32Array(4096);
|
||||||
i32[4] = 42;
|
i32[4] = 42;
|
||||||
assertEq(asmLink(asmCompileCached("g","ffis","buf", USE_ASM + "var i32=new g.Int32Array(buf); function f(i) { i=i|0; return i32[i>>2]|0 } return f"), this, null, i32.buffer)(4*4), 42);
|
assertEq(asmLink(asmCompileCached("g","ffis","buf", USE_ASM + "var i32=new g.Int32Array(buf); function f(i) { i=i|0; return i32[i>>2]|0 } return f"), this, null, i32.buffer)(4*4), 42);
|
||||||
|
assertEq(asmLink(asmCompileCached('glob', USE_ASM + 'var x=glob.Math.PI; function f() { return +x } return f'), this)(), Math.PI);
|
||||||
|
@ -86,3 +86,17 @@ assertAsmTypeFail('glob', USE_ASM + 'var im=glob.Math.imul; function f(i) { i=i|
|
|||||||
assertAsmTypeFail('glob', USE_ASM + 'var im=glob.Math.imul; function f(i) { i=i|0; i = im(i,i); } return f');
|
assertAsmTypeFail('glob', USE_ASM + 'var im=glob.Math.imul; function f(i) { i=i|0; i = im(i,i); } return f');
|
||||||
assertAsmTypeFail('glob', USE_ASM + 'var abs=glob.Math.abs; function f(i) { i=i|0; +abs(i|0); } return f');
|
assertAsmTypeFail('glob', USE_ASM + 'var abs=glob.Math.abs; function f(i) { i=i|0; +abs(i|0); } return f');
|
||||||
assertAsmTypeFail('glob', USE_ASM + 'var abs=glob.Math.abs; function f(d) { d=+d; abs(d)|0; } return f');
|
assertAsmTypeFail('glob', USE_ASM + 'var abs=glob.Math.abs; function f(d) { d=+d; abs(d)|0; } return f');
|
||||||
|
|
||||||
|
assertAsmTypeFail('glob', USE_ASM + 'var tau=glob.Math.TAU; function f() {} return f');
|
||||||
|
assertAsmTypeFail('glob', USE_ASM + 'var pi=glob.Math.PI; function f() { return pi | 0 } return f');
|
||||||
|
assertAsmTypeFail('glob', USE_ASM + 'var pi=glob.Math.PI; function f() { return +pi() } return f');
|
||||||
|
assertAsmTypeFail('glob', USE_ASM + 'var pi=glob.Math.PI; function f() { pi = +3; } return f');
|
||||||
|
assertAsmLinkAlwaysFail(asmCompile('glob', USE_ASM + 'var pi=glob.Math.PI; function f() {} return f'), {});
|
||||||
|
assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var pi=glob.Math.PI; function f() {} return f'), {Math: {}});
|
||||||
|
assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var pi=glob.Math.PI; function f() {} return f'), {Math: {PI: Math.cos}});
|
||||||
|
assertAsmLinkFail(asmCompile('glob', USE_ASM + 'var pi=glob.Math.PI; function f() {} return f'), {Math: {PI: Math.SQRT2}});
|
||||||
|
|
||||||
|
for (var c of ['E', 'LN10', 'LN2', 'LOG2E', 'LOG10E', 'PI', 'SQRT1_2', 'SQRT2']) {
|
||||||
|
var f = asmLink(asmCompile('glob', USE_ASM + 'var x=glob.Math.' + c +'; function f() { return +x } return f'), this);
|
||||||
|
assertEq(f(), eval('Math.' + c));
|
||||||
|
}
|
||||||
|
@ -936,7 +936,7 @@ class MOZ_STACK_CLASS ModuleCompiler
|
|||||||
FuncPtrTable,
|
FuncPtrTable,
|
||||||
FFI,
|
FFI,
|
||||||
ArrayView,
|
ArrayView,
|
||||||
MathBuiltin
|
MathBuiltinFunction
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -951,7 +951,7 @@ class MOZ_STACK_CLASS ModuleCompiler
|
|||||||
uint32_t funcPtrTableIndex_;
|
uint32_t funcPtrTableIndex_;
|
||||||
uint32_t ffiIndex_;
|
uint32_t ffiIndex_;
|
||||||
ArrayBufferView::ViewType viewType_;
|
ArrayBufferView::ViewType viewType_;
|
||||||
AsmJSMathBuiltin mathBuiltin_;
|
AsmJSMathBuiltinFunction mathBuiltinFunc_;
|
||||||
} u;
|
} u;
|
||||||
|
|
||||||
friend class ModuleCompiler;
|
friend class ModuleCompiler;
|
||||||
@ -994,9 +994,9 @@ class MOZ_STACK_CLASS ModuleCompiler
|
|||||||
JS_ASSERT(which_ == ArrayView);
|
JS_ASSERT(which_ == ArrayView);
|
||||||
return u.viewType_;
|
return u.viewType_;
|
||||||
}
|
}
|
||||||
AsmJSMathBuiltin mathBuiltin() const {
|
AsmJSMathBuiltinFunction mathBuiltinFunction() const {
|
||||||
JS_ASSERT(which_ == MathBuiltin);
|
JS_ASSERT(which_ == MathBuiltinFunction);
|
||||||
return u.mathBuiltin_;
|
return u.mathBuiltinFunc_;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1063,6 +1063,25 @@ class MOZ_STACK_CLASS ModuleCompiler
|
|||||||
|
|
||||||
typedef HashMap<ExitDescriptor, unsigned, ExitDescriptor> ExitMap;
|
typedef HashMap<ExitDescriptor, unsigned, ExitDescriptor> ExitMap;
|
||||||
|
|
||||||
|
struct MathBuiltin
|
||||||
|
{
|
||||||
|
enum Kind { Function, Constant };
|
||||||
|
Kind kind;
|
||||||
|
|
||||||
|
union {
|
||||||
|
double cst;
|
||||||
|
AsmJSMathBuiltinFunction func;
|
||||||
|
} u;
|
||||||
|
|
||||||
|
MathBuiltin() : kind(Kind(-1)) {}
|
||||||
|
MathBuiltin(double cst) : kind(Constant) {
|
||||||
|
u.cst = cst;
|
||||||
|
}
|
||||||
|
MathBuiltin(AsmJSMathBuiltinFunction func) : kind(Function) {
|
||||||
|
u.func = func;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct SlowFunction
|
struct SlowFunction
|
||||||
{
|
{
|
||||||
@ -1072,7 +1091,7 @@ class MOZ_STACK_CLASS ModuleCompiler
|
|||||||
unsigned column;
|
unsigned column;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef HashMap<PropertyName*, AsmJSMathBuiltin> MathNameMap;
|
typedef HashMap<PropertyName*, MathBuiltin> MathNameMap;
|
||||||
typedef HashMap<PropertyName*, Global*> GlobalMap;
|
typedef HashMap<PropertyName*, Global*> GlobalMap;
|
||||||
typedef js::Vector<Func*> FuncVector;
|
typedef js::Vector<Func*> FuncVector;
|
||||||
typedef js::Vector<AsmJSGlobalAccess> GlobalAccessVector;
|
typedef js::Vector<AsmJSGlobalAccess> GlobalAccessVector;
|
||||||
@ -1106,10 +1125,18 @@ class MOZ_STACK_CLASS ModuleCompiler
|
|||||||
|
|
||||||
DebugOnly<bool> finishedFunctionBodies_;
|
DebugOnly<bool> finishedFunctionBodies_;
|
||||||
|
|
||||||
bool addStandardLibraryMathName(const char *name, AsmJSMathBuiltin builtin) {
|
bool addStandardLibraryMathName(const char *name, AsmJSMathBuiltinFunction func) {
|
||||||
JSAtom *atom = Atomize(cx_, name, strlen(name));
|
JSAtom *atom = Atomize(cx_, name, strlen(name));
|
||||||
if (!atom)
|
if (!atom)
|
||||||
return false;
|
return false;
|
||||||
|
MathBuiltin builtin(func);
|
||||||
|
return standardLibraryMathNames_.putNew(atom->asPropertyName(), builtin);
|
||||||
|
}
|
||||||
|
bool addStandardLibraryMathName(const char *name, double cst) {
|
||||||
|
JSAtom *atom = Atomize(cx_, name, strlen(name));
|
||||||
|
if (!atom)
|
||||||
|
return false;
|
||||||
|
MathBuiltin builtin(cst);
|
||||||
return standardLibraryMathNames_.putNew(atom->asPropertyName(), builtin);
|
return standardLibraryMathNames_.putNew(atom->asPropertyName(), builtin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1175,7 +1202,15 @@ class MOZ_STACK_CLASS ModuleCompiler
|
|||||||
!addStandardLibraryMathName("abs", AsmJSMathBuiltin_abs) ||
|
!addStandardLibraryMathName("abs", AsmJSMathBuiltin_abs) ||
|
||||||
!addStandardLibraryMathName("atan2", AsmJSMathBuiltin_atan2) ||
|
!addStandardLibraryMathName("atan2", AsmJSMathBuiltin_atan2) ||
|
||||||
!addStandardLibraryMathName("imul", AsmJSMathBuiltin_imul) ||
|
!addStandardLibraryMathName("imul", AsmJSMathBuiltin_imul) ||
|
||||||
!addStandardLibraryMathName("fround", AsmJSMathBuiltin_fround))
|
!addStandardLibraryMathName("fround", AsmJSMathBuiltin_fround) ||
|
||||||
|
!addStandardLibraryMathName("E", M_E) ||
|
||||||
|
!addStandardLibraryMathName("LN10", M_LN10) ||
|
||||||
|
!addStandardLibraryMathName("LN2", M_LN2) ||
|
||||||
|
!addStandardLibraryMathName("LOG2E", M_LOG2E) ||
|
||||||
|
!addStandardLibraryMathName("LOG10E", M_LOG10E) ||
|
||||||
|
!addStandardLibraryMathName("PI", M_PI) ||
|
||||||
|
!addStandardLibraryMathName("SQRT1_2", M_SQRT1_2) ||
|
||||||
|
!addStandardLibraryMathName("SQRT2", M_SQRT2))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1289,7 +1324,7 @@ class MOZ_STACK_CLASS ModuleCompiler
|
|||||||
FuncPtrTable &funcPtrTable(unsigned i) {
|
FuncPtrTable &funcPtrTable(unsigned i) {
|
||||||
return funcPtrTables_[i];
|
return funcPtrTables_[i];
|
||||||
}
|
}
|
||||||
bool lookupStandardLibraryMathName(PropertyName *name, AsmJSMathBuiltin *mathBuiltin) const {
|
bool lookupStandardLibraryMathName(PropertyName *name, MathBuiltin *mathBuiltin) const {
|
||||||
if (MathNameMap::Ptr p = standardLibraryMathNames_.lookup(name)) {
|
if (MathNameMap::Ptr p = standardLibraryMathNames_.lookup(name)) {
|
||||||
*mathBuiltin = p->value();
|
*mathBuiltin = p->value();
|
||||||
return true;
|
return true;
|
||||||
@ -1390,18 +1425,17 @@ class MOZ_STACK_CLASS ModuleCompiler
|
|||||||
global->u.viewType_ = vt;
|
global->u.viewType_ = vt;
|
||||||
return globals_.putNew(varName, global);
|
return globals_.putNew(varName, global);
|
||||||
}
|
}
|
||||||
bool addMathBuiltin(PropertyName *varName, AsmJSMathBuiltin mathBuiltin, PropertyName *fieldName) {
|
bool addMathBuiltinFunction(PropertyName *varName, AsmJSMathBuiltinFunction func, PropertyName *fieldName) {
|
||||||
if (!module_->addMathBuiltin(mathBuiltin, fieldName))
|
if (!module_->addMathBuiltinFunction(func, fieldName))
|
||||||
return false;
|
return false;
|
||||||
Global *global = moduleLifo_.new_<Global>(Global::MathBuiltin);
|
Global *global = moduleLifo_.new_<Global>(Global::MathBuiltinFunction);
|
||||||
if (!global)
|
if (!global)
|
||||||
return false;
|
return false;
|
||||||
global->u.mathBuiltin_ = mathBuiltin;
|
global->u.mathBuiltinFunc_ = func;
|
||||||
return globals_.putNew(varName, global);
|
return globals_.putNew(varName, global);
|
||||||
}
|
}
|
||||||
bool addGlobalConstant(PropertyName *varName, double constant, PropertyName *fieldName) {
|
private:
|
||||||
if (!module_->addGlobalConstant(constant, fieldName))
|
bool addGlobalDoubleConstant(PropertyName *varName, double constant) {
|
||||||
return false;
|
|
||||||
Global *global = moduleLifo_.new_<Global>(Global::ConstantLiteral);
|
Global *global = moduleLifo_.new_<Global>(Global::ConstantLiteral);
|
||||||
if (!global)
|
if (!global)
|
||||||
return false;
|
return false;
|
||||||
@ -1409,6 +1443,17 @@ class MOZ_STACK_CLASS ModuleCompiler
|
|||||||
global->u.varOrConst.type_ = VarType::Double;
|
global->u.varOrConst.type_ = VarType::Double;
|
||||||
return globals_.putNew(varName, global);
|
return globals_.putNew(varName, global);
|
||||||
}
|
}
|
||||||
|
public:
|
||||||
|
bool addMathBuiltinConstant(PropertyName *varName, double constant, PropertyName *fieldName) {
|
||||||
|
if (!module_->addMathBuiltinConstant(constant, fieldName))
|
||||||
|
return false;
|
||||||
|
return addGlobalDoubleConstant(varName, constant);
|
||||||
|
}
|
||||||
|
bool addGlobalConstant(PropertyName *varName, double constant, PropertyName *fieldName) {
|
||||||
|
if (!module_->addGlobalConstant(constant, fieldName))
|
||||||
|
return false;
|
||||||
|
return addGlobalDoubleConstant(varName, constant);
|
||||||
|
}
|
||||||
bool addExportedFunction(const Func *func, PropertyName *maybeFieldName) {
|
bool addExportedFunction(const Func *func, PropertyName *maybeFieldName) {
|
||||||
AsmJSModule::ArgCoercionVector argCoercions;
|
AsmJSModule::ArgCoercionVector argCoercions;
|
||||||
const VarTypeVector &args = func->sig().args();
|
const VarTypeVector &args = func->sig().args();
|
||||||
@ -1774,8 +1819,8 @@ IsFloatCoercion(ModuleCompiler &m, ParseNode *pn, ParseNode **coercedExpr)
|
|||||||
|
|
||||||
const ModuleCompiler::Global *global = m.lookupGlobal(callee->name());
|
const ModuleCompiler::Global *global = m.lookupGlobal(callee->name());
|
||||||
if (!global ||
|
if (!global ||
|
||||||
global->which() != ModuleCompiler::Global::MathBuiltin ||
|
global->which() != ModuleCompiler::Global::MathBuiltinFunction ||
|
||||||
global->mathBuiltin() != AsmJSMathBuiltin_fround)
|
global->mathBuiltinFunction() != AsmJSMathBuiltin_fround)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -3104,11 +3149,19 @@ CheckGlobalDotImport(ModuleCompiler &m, PropertyName *varName, ParseNode *initNo
|
|||||||
if (!IsUseOfName(global, m.module().globalArgumentName()) || math != m.cx()->names().Math)
|
if (!IsUseOfName(global, m.module().globalArgumentName()) || math != m.cx()->names().Math)
|
||||||
return m.fail(base, "expecting global.Math");
|
return m.fail(base, "expecting global.Math");
|
||||||
|
|
||||||
AsmJSMathBuiltin mathBuiltin;
|
ModuleCompiler::MathBuiltin mathBuiltin;
|
||||||
if (!m.lookupStandardLibraryMathName(field, &mathBuiltin))
|
if (!m.lookupStandardLibraryMathName(field, &mathBuiltin))
|
||||||
return m.failName(initNode, "'%s' is not a standard Math builtin", field);
|
return m.failName(initNode, "'%s' is not a standard Math builtin", field);
|
||||||
|
|
||||||
return m.addMathBuiltin(varName, mathBuiltin, field);
|
switch (mathBuiltin.kind) {
|
||||||
|
case ModuleCompiler::MathBuiltin::Function:
|
||||||
|
return m.addMathBuiltinFunction(varName, mathBuiltin.u.func, field);
|
||||||
|
case ModuleCompiler::MathBuiltin::Constant:
|
||||||
|
return m.addMathBuiltinConstant(varName, mathBuiltin.u.cst, field);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
MOZ_ASSUME_UNREACHABLE("unexpected or uninitialized math builtin type");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsUseOfName(base, m.module().globalArgumentName())) {
|
if (IsUseOfName(base, m.module().globalArgumentName())) {
|
||||||
@ -3366,7 +3419,7 @@ CheckVarRef(FunctionCompiler &f, ParseNode *varRef, MDefinition **def, Type *typ
|
|||||||
break;
|
break;
|
||||||
case ModuleCompiler::Global::Function:
|
case ModuleCompiler::Global::Function:
|
||||||
case ModuleCompiler::Global::FFI:
|
case ModuleCompiler::Global::FFI:
|
||||||
case ModuleCompiler::Global::MathBuiltin:
|
case ModuleCompiler::Global::MathBuiltinFunction:
|
||||||
case ModuleCompiler::Global::FuncPtrTable:
|
case ModuleCompiler::Global::FuncPtrTable:
|
||||||
case ModuleCompiler::Global::ArrayView:
|
case ModuleCompiler::Global::ArrayView:
|
||||||
return f.failName(varRef, "'%s' may not be accessed by ordinary expressions", name);
|
return f.failName(varRef, "'%s' may not be accessed by ordinary expressions", name);
|
||||||
@ -4021,12 +4074,12 @@ CheckIsMaybeFloat(FunctionCompiler &f, ParseNode *argNode, Type type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
CheckMathBuiltinCall(FunctionCompiler &f, ParseNode *callNode, AsmJSMathBuiltin mathBuiltin,
|
CheckMathBuiltinCall(FunctionCompiler &f, ParseNode *callNode, AsmJSMathBuiltinFunction func,
|
||||||
RetType retType, MDefinition **def, Type *type)
|
RetType retType, MDefinition **def, Type *type)
|
||||||
{
|
{
|
||||||
unsigned arity = 0;
|
unsigned arity = 0;
|
||||||
AsmJSImmKind doubleCallee, floatCallee;
|
AsmJSImmKind doubleCallee, floatCallee;
|
||||||
switch (mathBuiltin) {
|
switch (func) {
|
||||||
case AsmJSMathBuiltin_imul: return CheckMathIMul(f, callNode, retType, def, type);
|
case AsmJSMathBuiltin_imul: return CheckMathIMul(f, callNode, retType, def, type);
|
||||||
case AsmJSMathBuiltin_abs: return CheckMathAbs(f, callNode, retType, def, type);
|
case AsmJSMathBuiltin_abs: return CheckMathAbs(f, callNode, retType, def, type);
|
||||||
case AsmJSMathBuiltin_sqrt: return CheckMathSqrt(f, callNode, retType, def, type);
|
case AsmJSMathBuiltin_sqrt: return CheckMathSqrt(f, callNode, retType, def, type);
|
||||||
@ -4043,7 +4096,7 @@ CheckMathBuiltinCall(FunctionCompiler &f, ParseNode *callNode, AsmJSMathBuiltin
|
|||||||
case AsmJSMathBuiltin_log: arity = 1; doubleCallee = AsmJSImm_LogD; floatCallee = AsmJSImm_LogF; break;
|
case AsmJSMathBuiltin_log: arity = 1; doubleCallee = AsmJSImm_LogD; floatCallee = AsmJSImm_LogF; break;
|
||||||
case AsmJSMathBuiltin_pow: arity = 2; doubleCallee = AsmJSImm_PowD; floatCallee = AsmJSImm_Invalid; break;
|
case AsmJSMathBuiltin_pow: arity = 2; doubleCallee = AsmJSImm_PowD; floatCallee = AsmJSImm_Invalid; break;
|
||||||
case AsmJSMathBuiltin_atan2: arity = 2; doubleCallee = AsmJSImm_ATan2D; floatCallee = AsmJSImm_Invalid; break;
|
case AsmJSMathBuiltin_atan2: arity = 2; doubleCallee = AsmJSImm_ATan2D; floatCallee = AsmJSImm_Invalid; break;
|
||||||
default: MOZ_ASSUME_UNREACHABLE("unexpected mathBuiltin");
|
default: MOZ_ASSUME_UNREACHABLE("unexpected mathBuiltin function");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retType == RetType::Float && floatCallee == AsmJSImm_Invalid)
|
if (retType == RetType::Float && floatCallee == AsmJSImm_Invalid)
|
||||||
@ -4088,8 +4141,8 @@ CheckCall(FunctionCompiler &f, ParseNode *call, RetType retType, MDefinition **d
|
|||||||
switch (global->which()) {
|
switch (global->which()) {
|
||||||
case ModuleCompiler::Global::FFI:
|
case ModuleCompiler::Global::FFI:
|
||||||
return CheckFFICall(f, call, global->ffiIndex(), retType, def, type);
|
return CheckFFICall(f, call, global->ffiIndex(), retType, def, type);
|
||||||
case ModuleCompiler::Global::MathBuiltin:
|
case ModuleCompiler::Global::MathBuiltinFunction:
|
||||||
return CheckMathBuiltinCall(f, call, global->mathBuiltin(), retType, def, type);
|
return CheckMathBuiltinCall(f, call, global->mathBuiltinFunction(), retType, def, type);
|
||||||
case ModuleCompiler::Global::ConstantLiteral:
|
case ModuleCompiler::Global::ConstantLiteral:
|
||||||
case ModuleCompiler::Global::ConstantImport:
|
case ModuleCompiler::Global::ConstantImport:
|
||||||
case ModuleCompiler::Global::Variable:
|
case ModuleCompiler::Global::Variable:
|
||||||
|
@ -143,7 +143,7 @@ ValidateArrayView(JSContext *cx, AsmJSModule::Global &global, HandleValue global
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
ValidateMathBuiltin(JSContext *cx, AsmJSModule::Global &global, HandleValue globalVal)
|
ValidateMathBuiltinFunction(JSContext *cx, AsmJSModule::Global &global, HandleValue globalVal)
|
||||||
{
|
{
|
||||||
RootedValue v(cx);
|
RootedValue v(cx);
|
||||||
if (!GetDataProperty(cx, globalVal, cx->names().Math, &v))
|
if (!GetDataProperty(cx, globalVal, cx->names().Math, &v))
|
||||||
@ -153,7 +153,7 @@ ValidateMathBuiltin(JSContext *cx, AsmJSModule::Global &global, HandleValue glob
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
Native native = nullptr;
|
Native native = nullptr;
|
||||||
switch (global.mathBuiltin()) {
|
switch (global.mathBuiltinFunction()) {
|
||||||
case AsmJSMathBuiltin_sin: native = math_sin; break;
|
case AsmJSMathBuiltin_sin: native = math_sin; break;
|
||||||
case AsmJSMathBuiltin_cos: native = math_cos; break;
|
case AsmJSMathBuiltin_cos: native = math_cos; break;
|
||||||
case AsmJSMathBuiltin_tan: native = math_tan; break;
|
case AsmJSMathBuiltin_tan: native = math_tan; break;
|
||||||
@ -173,21 +173,26 @@ ValidateMathBuiltin(JSContext *cx, AsmJSModule::Global &global, HandleValue glob
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!IsNativeFunction(v, native))
|
if (!IsNativeFunction(v, native))
|
||||||
return LinkFail(cx, "bad Math.* builtin");
|
return LinkFail(cx, "bad Math.* builtin function");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
ValidateGlobalConstant(JSContext *cx, AsmJSModule::Global &global, HandleValue globalVal)
|
ValidateConstant(JSContext *cx, AsmJSModule::Global &global, HandleValue globalVal)
|
||||||
{
|
{
|
||||||
RootedPropertyName field(cx, global.constantName());
|
RootedPropertyName field(cx, global.constantName());
|
||||||
RootedValue v(cx);
|
RootedValue v(cx, globalVal);
|
||||||
if (!GetDataProperty(cx, globalVal, field, &v))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
|
if (global.constantKind() == AsmJSModule::Global::MathConstant) {
|
||||||
|
if (!GetDataProperty(cx, v, cx->names().Math, &v))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GetDataProperty(cx, v, field, &v))
|
||||||
|
return false;
|
||||||
if (!v.isNumber())
|
if (!v.isNumber())
|
||||||
return LinkFail(cx, "global constant value needs to be a number");
|
return LinkFail(cx, "math / global constant value needs to be a number");
|
||||||
|
|
||||||
// NaN != NaN
|
// NaN != NaN
|
||||||
if (IsNaN(global.constantValue())) {
|
if (IsNaN(global.constantValue())) {
|
||||||
@ -269,12 +274,12 @@ DynamicallyLinkModule(JSContext *cx, CallArgs args, AsmJSModule &module)
|
|||||||
if (!ValidateArrayView(cx, global, globalVal, bufferVal))
|
if (!ValidateArrayView(cx, global, globalVal, bufferVal))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case AsmJSModule::Global::MathBuiltin:
|
case AsmJSModule::Global::MathBuiltinFunction:
|
||||||
if (!ValidateMathBuiltin(cx, global, globalVal))
|
if (!ValidateMathBuiltinFunction(cx, global, globalVal))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case AsmJSModule::Global::Constant:
|
case AsmJSModule::Global::Constant:
|
||||||
if (!ValidateGlobalConstant(cx, global, globalVal))
|
if (!ValidateConstant(cx, global, globalVal))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ enum AsmJSCoercion
|
|||||||
};
|
};
|
||||||
|
|
||||||
// The asm.js spec recognizes this set of builtin Math functions.
|
// The asm.js spec recognizes this set of builtin Math functions.
|
||||||
enum AsmJSMathBuiltin
|
enum AsmJSMathBuiltinFunction
|
||||||
{
|
{
|
||||||
AsmJSMathBuiltin_sin, AsmJSMathBuiltin_cos, AsmJSMathBuiltin_tan,
|
AsmJSMathBuiltin_sin, AsmJSMathBuiltin_cos, AsmJSMathBuiltin_tan,
|
||||||
AsmJSMathBuiltin_asin, AsmJSMathBuiltin_acos, AsmJSMathBuiltin_atan,
|
AsmJSMathBuiltin_asin, AsmJSMathBuiltin_acos, AsmJSMathBuiltin_atan,
|
||||||
@ -97,8 +97,9 @@ class AsmJSModule
|
|||||||
class Global
|
class Global
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Which { Variable, FFI, ArrayView, MathBuiltin, Constant };
|
enum Which { Variable, FFI, ArrayView, MathBuiltinFunction, Constant };
|
||||||
enum VarInitKind { InitConstant, InitImport };
|
enum VarInitKind { InitConstant, InitImport };
|
||||||
|
enum ConstantKind { GlobalConstant, MathConstant };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Pod {
|
struct Pod {
|
||||||
@ -114,8 +115,11 @@ class AsmJSModule
|
|||||||
} var;
|
} var;
|
||||||
uint32_t ffiIndex_;
|
uint32_t ffiIndex_;
|
||||||
ArrayBufferView::ViewType viewType_;
|
ArrayBufferView::ViewType viewType_;
|
||||||
AsmJSMathBuiltin mathBuiltin_;
|
AsmJSMathBuiltinFunction mathBuiltinFunc_;
|
||||||
double constantValue_;
|
struct {
|
||||||
|
ConstantKind kind_;
|
||||||
|
double value_;
|
||||||
|
} constant;
|
||||||
} u;
|
} u;
|
||||||
} pod;
|
} pod;
|
||||||
PropertyName *name_;
|
PropertyName *name_;
|
||||||
@ -179,20 +183,24 @@ class AsmJSModule
|
|||||||
return pod.u.viewType_;
|
return pod.u.viewType_;
|
||||||
}
|
}
|
||||||
PropertyName *mathName() const {
|
PropertyName *mathName() const {
|
||||||
JS_ASSERT(pod.which_ == MathBuiltin);
|
JS_ASSERT(pod.which_ == MathBuiltinFunction);
|
||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
AsmJSMathBuiltin mathBuiltin() const {
|
AsmJSMathBuiltinFunction mathBuiltinFunction() const {
|
||||||
JS_ASSERT(pod.which_ == MathBuiltin);
|
JS_ASSERT(pod.which_ == MathBuiltinFunction);
|
||||||
return pod.u.mathBuiltin_;
|
return pod.u.mathBuiltinFunc_;
|
||||||
}
|
}
|
||||||
PropertyName *constantName() const {
|
PropertyName *constantName() const {
|
||||||
JS_ASSERT(pod.which_ == Constant);
|
JS_ASSERT(pod.which_ == Constant);
|
||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
|
ConstantKind constantKind() const {
|
||||||
|
JS_ASSERT(pod.which_ == Constant);
|
||||||
|
return pod.u.constant.kind_;
|
||||||
|
}
|
||||||
double constantValue() const {
|
double constantValue() const {
|
||||||
JS_ASSERT(pod.which_ == Constant);
|
JS_ASSERT(pod.which_ == Constant);
|
||||||
return pod.u.constantValue_;
|
return pod.u.constant.value_;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t serializedSize() const;
|
size_t serializedSize() const;
|
||||||
@ -488,14 +496,21 @@ class AsmJSModule
|
|||||||
g.pod.u.viewType_ = vt;
|
g.pod.u.viewType_ = vt;
|
||||||
return globals_.append(g);
|
return globals_.append(g);
|
||||||
}
|
}
|
||||||
bool addMathBuiltin(AsmJSMathBuiltin mathBuiltin, PropertyName *field) {
|
bool addMathBuiltinFunction(AsmJSMathBuiltinFunction func, PropertyName *field) {
|
||||||
Global g(Global::MathBuiltin, field);
|
Global g(Global::MathBuiltinFunction, field);
|
||||||
g.pod.u.mathBuiltin_ = mathBuiltin;
|
g.pod.u.mathBuiltinFunc_ = func;
|
||||||
|
return globals_.append(g);
|
||||||
|
}
|
||||||
|
bool addMathBuiltinConstant(double value, PropertyName *field) {
|
||||||
|
Global g(Global::Constant, field);
|
||||||
|
g.pod.u.constant.value_ = value;
|
||||||
|
g.pod.u.constant.kind_ = Global::MathConstant;
|
||||||
return globals_.append(g);
|
return globals_.append(g);
|
||||||
}
|
}
|
||||||
bool addGlobalConstant(double value, PropertyName *name) {
|
bool addGlobalConstant(double value, PropertyName *name) {
|
||||||
Global g(Global::Constant, name);
|
Global g(Global::Constant, name);
|
||||||
g.pod.u.constantValue_ = value;
|
g.pod.u.constant.value_ = value;
|
||||||
|
g.pod.u.constant.kind_ = Global::GlobalConstant;
|
||||||
return globals_.append(g);
|
return globals_.append(g);
|
||||||
}
|
}
|
||||||
bool addFuncPtrTable(unsigned numElems, uint32_t *globalDataOffset) {
|
bool addFuncPtrTable(unsigned numElems, uint32_t *globalDataOffset) {
|
||||||
|
Loading…
Reference in New Issue
Block a user