1 /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
2 /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is [Open Source Virtual Machine.].
18 * The Initial Developer of the Original Code is
19 * Adobe System Incorporated.
20 * Portions created by the Initial Developer are Copyright (C) 2004-2006
21 * the Initial Developer. All Rights Reserved.
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
42 #include "BuiltinNatives.h"
46 NumberClass::NumberClass(VTable
* cvtable
)
47 : ClassClosure(cvtable
)
49 toplevel()->_numberClass
= this;
51 // prototype objects are always vanilla objects.
52 createVanillaPrototype();
55 Atom
NumberClass::construct(int argc
, Atom
* argv
)
57 // Number called as constructor creates new Number instance
58 // Note: SpiderMonkey returns 0 for new Number() with no args
60 return zeroIntAtom
; // yep this is zero atom
62 return core()->numberAtom(argv
[1]);
63 // TODO ArgumentError if argc > 1
66 Stringp
NumberClass::_convert(double n
, int precision
, int mode
)
68 AvmCore
* core
= this->core();
70 if (mode
== MathUtils::DTOSTR_PRECISION
)
72 if (precision
< 1 || precision
> 21) {
73 toplevel()->throwRangeError(kInvalidPrecisionError
, core
->toErrorString(precision
), core
->toErrorString(1), core
->toErrorString(21));
78 if (precision
< 0 || precision
> 20) {
79 toplevel()->throwRangeError(kInvalidPrecisionError
, core
->toErrorString(precision
), core
->toErrorString(0), core
->toErrorString(20));
83 return MathUtils::convertDoubleToString(core
, n
, mode
, precision
);
86 Stringp
NumberClass::_numberToString(double dVal
, int radix
)
88 AvmCore
* core
= this->core();
90 if (radix
== 10 || MathUtils::isInfinite(dVal
) || MathUtils::isNaN(dVal
))
91 return core
->doubleToString(dVal
);
93 if (radix
< 2 || radix
> 36)
94 toplevel()->throwRangeError(kInvalidRadixError
, core
->toErrorString(radix
));
96 // convertDoubleToStringRadix will convert the integer part of dVal
97 // to a string in the specified radix, and it will handle large numbers
98 // beyond the range of int/uint. It will not handle the fractional
99 // part. To properly handle that, MathUtils::convertDoubleToString
100 // would have to handle any base. That's a lot of extra code and complexity for
101 // something the ES3 spec says is implementation dependent
102 // (i.e. we're not required to do it)
104 return MathUtils::convertDoubleToStringRadix(core
, dVal
, radix
);
107 // volatile externals to keep the constant propagator from outsmarting us.
108 volatile double minDouble
= 4.94e-324;
109 volatile double minNormalizedDouble
= 2.2250738585072014e-308; // really needs all these digits to get it right
111 double NumberClass::_minValue()
113 // https://bugzilla.mozilla.org/show_bug.cgi?id=555805
115 // The ARM architecture saves transistors by not implementing subnormal floating point numbers in
116 // hardware. Instead, those values produce a trap ("bounce") so that they can be emulated in software.
117 // There is, however, a "RunFast" mode that suppresses the "bounce" and instead does a
118 // "flush-to-zero" on underflow. Some platforms operate in RunFast mode by default and while it
119 // is possible for user code to turn off that mode, it seems to be in the OS's purview to install
120 // the trap handler. Long story short, on certain ARM-based platforms, values smaller than the smallest
121 // normalized floating point value are snapped (flushed) to zero.
123 // The definitive reference URLs appear to be perishable, but the terms in quotes above are useful in searches:
124 // http://www.google.com/search?q=ARM+runfast+flush-to-zero+bounce
126 // The issue seems specific to ARM processors (though perhaps other mobilized cores as well), but will only occur
127 // if the platform opts not to install an emulator trap. So we dynamically find the smallest value, being wary of
128 // techniques that might be optimized away by compilers (and especially cross-compilers!).
130 double minValue
= minDouble
;
132 minValue
= minNormalizedDouble
;
134 // It's going to be either 0x1 (~4.94e-324) if subnormals are supported or 0x0010000000000000 (~2.225e-308) if not.
135 double_overlay
d(minValue
);
136 AvmAssert((d
.words
.msw
== 0 && d
.words
.lsw
== 1) || (d
.words
.msw
== 0x00100000 && d
.words
.lsw
== 0));