source: webkit/trunk/JavaScriptCore/runtime/MathObject.cpp@ 42478

Last change on this file since 42478 was 40968, checked in by [email protected], 16 years ago

Math.random is really slow on windows.

Reviewed by Jon Honeycutt.

Math.random calls WTF::randomNumber which is implemented as
the secure rand_s on windows. Unfortunately rand_s is an order
of magnitude slower than arc4random. For this reason I've
added "weakRandomNumber" for use by JavaScript's Math Object.
In the long term we should look at using our own secure PRNG
in place of the system, but this will do for now.

30% win on SunSpider on Windows, resolving most of the remaining
disparity vs. Mac.

  • Property svn:eol-style set to native
File size: 9.5 KB
Line 
1/*
2 * Copyright (C) 1999-2000 Harri Porten ([email protected])
3 * Copyright (C) 2007, 2008 Apple Inc. All Rights Reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 */
20
21#include "config.h"
22#include "MathObject.h"
23
24#include "ObjectPrototype.h"
25#include "Operations.h"
26#include <time.h>
27#include <wtf/Assertions.h>
28#include <wtf/MathExtras.h>
29#include <wtf/RandomNumber.h>
30#include <wtf/RandomNumberSeed.h>
31
32namespace JSC {
33
34ASSERT_CLASS_FITS_IN_CELL(MathObject);
35
36static JSValuePtr mathProtoFuncAbs(ExecState*, JSObject*, JSValuePtr, const ArgList&);
37static JSValuePtr mathProtoFuncACos(ExecState*, JSObject*, JSValuePtr, const ArgList&);
38static JSValuePtr mathProtoFuncASin(ExecState*, JSObject*, JSValuePtr, const ArgList&);
39static JSValuePtr mathProtoFuncATan(ExecState*, JSObject*, JSValuePtr, const ArgList&);
40static JSValuePtr mathProtoFuncATan2(ExecState*, JSObject*, JSValuePtr, const ArgList&);
41static JSValuePtr mathProtoFuncCeil(ExecState*, JSObject*, JSValuePtr, const ArgList&);
42static JSValuePtr mathProtoFuncCos(ExecState*, JSObject*, JSValuePtr, const ArgList&);
43static JSValuePtr mathProtoFuncExp(ExecState*, JSObject*, JSValuePtr, const ArgList&);
44static JSValuePtr mathProtoFuncFloor(ExecState*, JSObject*, JSValuePtr, const ArgList&);
45static JSValuePtr mathProtoFuncLog(ExecState*, JSObject*, JSValuePtr, const ArgList&);
46static JSValuePtr mathProtoFuncMax(ExecState*, JSObject*, JSValuePtr, const ArgList&);
47static JSValuePtr mathProtoFuncMin(ExecState*, JSObject*, JSValuePtr, const ArgList&);
48static JSValuePtr mathProtoFuncPow(ExecState*, JSObject*, JSValuePtr, const ArgList&);
49static JSValuePtr mathProtoFuncRandom(ExecState*, JSObject*, JSValuePtr, const ArgList&);
50static JSValuePtr mathProtoFuncRound(ExecState*, JSObject*, JSValuePtr, const ArgList&);
51static JSValuePtr mathProtoFuncSin(ExecState*, JSObject*, JSValuePtr, const ArgList&);
52static JSValuePtr mathProtoFuncSqrt(ExecState*, JSObject*, JSValuePtr, const ArgList&);
53static JSValuePtr mathProtoFuncTan(ExecState*, JSObject*, JSValuePtr, const ArgList&);
54
55}
56
57#include "MathObject.lut.h"
58
59namespace JSC {
60
61// ------------------------------ MathObject --------------------------------
62
63const ClassInfo MathObject::info = { "Math", 0, 0, ExecState::mathTable };
64
65/* Source for MathObject.lut.h
66@begin mathTable
67 abs mathProtoFuncAbs DontEnum|Function 1
68 acos mathProtoFuncACos DontEnum|Function 1
69 asin mathProtoFuncASin DontEnum|Function 1
70 atan mathProtoFuncATan DontEnum|Function 1
71 atan2 mathProtoFuncATan2 DontEnum|Function 2
72 ceil mathProtoFuncCeil DontEnum|Function 1
73 cos mathProtoFuncCos DontEnum|Function 1
74 exp mathProtoFuncExp DontEnum|Function 1
75 floor mathProtoFuncFloor DontEnum|Function 1
76 log mathProtoFuncLog DontEnum|Function 1
77 max mathProtoFuncMax DontEnum|Function 2
78 min mathProtoFuncMin DontEnum|Function 2
79 pow mathProtoFuncPow DontEnum|Function 2
80 random mathProtoFuncRandom DontEnum|Function 0
81 round mathProtoFuncRound DontEnum|Function 1
82 sin mathProtoFuncSin DontEnum|Function 1
83 sqrt mathProtoFuncSqrt DontEnum|Function 1
84 tan mathProtoFuncTan DontEnum|Function 1
85@end
86*/
87
88MathObject::MathObject(ExecState* exec, PassRefPtr<Structure> structure)
89 : JSObject(structure)
90{
91 putDirectWithoutTransition(Identifier(exec, "E"), jsNumber(exec, exp(1.0)), DontDelete | DontEnum | ReadOnly);
92 putDirectWithoutTransition(Identifier(exec, "LN2"), jsNumber(exec, log(2.0)), DontDelete | DontEnum | ReadOnly);
93 putDirectWithoutTransition(Identifier(exec, "LN10"), jsNumber(exec, log(10.0)), DontDelete | DontEnum | ReadOnly);
94 putDirectWithoutTransition(Identifier(exec, "LOG2E"), jsNumber(exec, 1.0 / log(2.0)), DontDelete | DontEnum | ReadOnly);
95 putDirectWithoutTransition(Identifier(exec, "LOG10E"), jsNumber(exec, 1.0 / log(10.0)), DontDelete | DontEnum | ReadOnly);
96 putDirectWithoutTransition(Identifier(exec, "PI"), jsNumber(exec, piDouble), DontDelete | DontEnum | ReadOnly);
97 putDirectWithoutTransition(Identifier(exec, "SQRT1_2"), jsNumber(exec, sqrt(0.5)), DontDelete | DontEnum | ReadOnly);
98 putDirectWithoutTransition(Identifier(exec, "SQRT2"), jsNumber(exec, sqrt(2.0)), DontDelete | DontEnum | ReadOnly);
99 WTF::initializeWeakRandomNumberGenerator();
100}
101
102// ECMA 15.8
103
104bool MathObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
105{
106 const HashEntry* entry = ExecState::mathTable(exec)->entry(exec, propertyName);
107
108 if (!entry)
109 return JSObject::getOwnPropertySlot(exec, propertyName, slot);
110
111 ASSERT(entry->attributes() & Function);
112 setUpStaticFunctionSlot(exec, entry, this, propertyName, slot);
113 return true;
114}
115
116// ------------------------------ Functions --------------------------------
117
118JSValuePtr mathProtoFuncAbs(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
119{
120 return jsNumber(exec, fabs(args.at(exec, 0).toNumber(exec)));
121}
122
123JSValuePtr mathProtoFuncACos(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
124{
125 return jsNumber(exec, acos(args.at(exec, 0).toNumber(exec)));
126}
127
128JSValuePtr mathProtoFuncASin(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
129{
130 return jsNumber(exec, asin(args.at(exec, 0).toNumber(exec)));
131}
132
133JSValuePtr mathProtoFuncATan(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
134{
135 return jsNumber(exec, atan(args.at(exec, 0).toNumber(exec)));
136}
137
138JSValuePtr mathProtoFuncATan2(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
139{
140 return jsNumber(exec, atan2(args.at(exec, 0).toNumber(exec), args.at(exec, 1).toNumber(exec)));
141}
142
143JSValuePtr mathProtoFuncCeil(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
144{
145 return jsNumber(exec, ceil(args.at(exec, 0).toNumber(exec)));
146}
147
148JSValuePtr mathProtoFuncCos(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
149{
150 return jsNumber(exec, cos(args.at(exec, 0).toNumber(exec)));
151}
152
153JSValuePtr mathProtoFuncExp(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
154{
155 return jsNumber(exec, exp(args.at(exec, 0).toNumber(exec)));
156}
157
158JSValuePtr mathProtoFuncFloor(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
159{
160 return jsNumber(exec, floor(args.at(exec, 0).toNumber(exec)));
161}
162
163JSValuePtr mathProtoFuncLog(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
164{
165 return jsNumber(exec, log(args.at(exec, 0).toNumber(exec)));
166}
167
168JSValuePtr mathProtoFuncMax(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
169{
170 unsigned argsCount = args.size();
171 double result = -Inf;
172 for (unsigned k = 0; k < argsCount; ++k) {
173 double val = args.at(exec, k).toNumber(exec);
174 if (isnan(val)) {
175 result = NaN;
176 break;
177 }
178 if (val > result || (val == 0 && result == 0 && !signbit(val)))
179 result = val;
180 }
181 return jsNumber(exec, result);
182}
183
184JSValuePtr mathProtoFuncMin(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
185{
186 unsigned argsCount = args.size();
187 double result = +Inf;
188 for (unsigned k = 0; k < argsCount; ++k) {
189 double val = args.at(exec, k).toNumber(exec);
190 if (isnan(val)) {
191 result = NaN;
192 break;
193 }
194 if (val < result || (val == 0 && result == 0 && signbit(val)))
195 result = val;
196 }
197 return jsNumber(exec, result);
198}
199
200JSValuePtr mathProtoFuncPow(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
201{
202 // ECMA 15.8.2.1.13
203
204 double arg = args.at(exec, 0).toNumber(exec);
205 double arg2 = args.at(exec, 1).toNumber(exec);
206
207 if (isnan(arg2))
208 return jsNaN(exec);
209 if (isinf(arg2) && fabs(arg) == 1)
210 return jsNaN(exec);
211 return jsNumber(exec, pow(arg, arg2));
212}
213
214JSValuePtr mathProtoFuncRandom(ExecState* exec, JSObject*, JSValuePtr, const ArgList&)
215{
216 return jsNumber(exec, WTF::weakRandomNumber());
217}
218
219JSValuePtr mathProtoFuncRound(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
220{
221 double arg = args.at(exec, 0).toNumber(exec);
222 if (signbit(arg) && arg >= -0.5)
223 return jsNumber(exec, -0.0);
224 return jsNumber(exec, floor(arg + 0.5));
225}
226
227JSValuePtr mathProtoFuncSin(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
228{
229 return jsNumber(exec, sin(args.at(exec, 0).toNumber(exec)));
230}
231
232JSValuePtr mathProtoFuncSqrt(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
233{
234 return jsNumber(exec, sqrt(args.at(exec, 0).toNumber(exec)));
235}
236
237JSValuePtr mathProtoFuncTan(ExecState* exec, JSObject*, JSValuePtr, const ArgList& args)
238{
239 return jsNumber(exec, tan(args.at(exec, 0).toNumber(exec)));
240}
241
242} // namespace JSC
Note: See TracBrowser for help on using the repository browser.