Unreviewed, rolling out r241784.
[WebKit-https.git] / Source / JavaScriptCore / dynbench.cpp
1 /*
2  * Copyright (C) 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27
28 #include "Identifier.h"
29 #include "InitializeThreading.h"
30 #include "JSCInlines.h"
31 #include "JSCJSValue.h"
32 #include "JSGlobalObject.h"
33 #include "JSLock.h"
34 #include "JSObject.h"
35 #include "VM.h"
36 #include <wtf/MainThread.h>
37
38 using namespace JSC;
39
40 namespace {
41
42 Lock crashLock;
43 const char* nameFilter;
44 unsigned requestedIterationCount;
45
46 #define CHECK(x) do {                                                   \
47         if (!!(x))                                                      \
48             break;                                                      \
49         crashLock.lock();                                               \
50         WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #x); \
51         CRASH();                                                        \
52     } while (false)
53
54 template<typename Callback>
55 NEVER_INLINE void benchmarkImpl(const char* name, unsigned iterationCount, const Callback& callback)
56 {
57     if (nameFilter && !strcasestr(name, nameFilter))
58         return;
59
60     if (requestedIterationCount)
61         iterationCount = requestedIterationCount;
62     
63     MonotonicTime before = MonotonicTime::now();
64     callback(iterationCount);
65     MonotonicTime after = MonotonicTime::now();
66     dataLog(name, ": ", (after - before).milliseconds(), " ms.\n");
67 }
68
69 } // anonymous namespace
70
71 int main(int argc, char** argv)
72 {
73     if (argc >= 2) {
74         if (argv[1][0] == '-') {
75             dataLog("Usage: dynbench [<filter> [<iteration count>]]\n");
76             return 1;
77         }
78
79         nameFilter = argv[1];
80
81         if (argc >= 3) {
82             if (sscanf(argv[2], "%u", &requestedIterationCount) != 1) {
83                 dataLog("Could not parse iteration count ", argv[2], "\n");
84                 return 1;
85             }
86         }
87     }
88     
89     WTF::initializeMainThread();
90     JSC::initializeThreading();
91
92     VM* vm = &VM::create(LargeHeap).leakRef();
93     {
94         JSLockHolder locker(vm);
95
96         JSGlobalObject* globalObject =
97             JSGlobalObject::create(*vm, JSGlobalObject::createStructure(*vm, jsNull()));
98         ExecState* exec = globalObject->globalExec();
99
100         Identifier identF = Identifier::fromString(exec, "f");
101         Identifier identG = Identifier::fromString(exec, "g");
102
103         Structure* objectStructure =
104             JSFinalObject::createStructure(*vm, globalObject, globalObject->objectPrototype(), 2);
105
106         // Non-strict dynamic get by id:
107         JSValue object = JSFinalObject::create(*vm, objectStructure);
108         {
109             PutPropertySlot slot(object, false, PutPropertySlot::PutById);
110             object.putInline(exec, identF, jsNumber(42), slot);
111         }
112         {
113             PutPropertySlot slot(object, false, PutPropertySlot::PutById);
114             object.putInline(exec, identG, jsNumber(43), slot);
115         }
116         benchmarkImpl(
117             "Non Strict Dynamic Get By Id",
118             1000000,
119             [&] (unsigned iterationCount) {
120                 for (unsigned i = iterationCount; i--;) {
121                     JSValue result = object.get(exec, identF);
122                     CHECK(result == jsNumber(42));
123                     result = object.get(exec, identG);
124                     CHECK(result == jsNumber(43));
125                 }
126             });
127
128         // Non-strict dynamic put by id replace:
129         object = JSFinalObject::create(*vm, objectStructure);
130         {
131             PutPropertySlot slot(object, false, PutPropertySlot::PutById);
132             object.putInline(exec, identF, jsNumber(42), slot);
133         }
134         {
135             PutPropertySlot slot(object, false, PutPropertySlot::PutById);
136             object.putInline(exec, identG, jsNumber(43), slot);
137         }
138         benchmarkImpl(
139             "Non Strict Dynamic Put By Id Replace",
140             1000000,
141             [&] (unsigned iterationCount) {
142                 for (unsigned i = iterationCount; i--;) {
143                     {
144                         PutPropertySlot slot(object, false, PutPropertySlot::PutById);
145                         object.putInline(exec, identF, jsNumber(i), slot);
146                     }
147                     {
148                         PutPropertySlot slot(object, false, PutPropertySlot::PutById);
149                         object.putInline(exec, identG, jsNumber(i), slot);
150                     }
151                 }
152             });
153
154         // Non-strict dynamic put by id transition with object allocation:
155         benchmarkImpl(
156             "Non Strict Dynamic Allocation and Put By Id Transition",
157             1000000,
158             [&] (unsigned iterationCount) {
159                 for (unsigned i = iterationCount; i--;) {
160                     JSValue object = JSFinalObject::create(*vm, objectStructure);
161                     {
162                         PutPropertySlot slot(object, false, PutPropertySlot::PutById);
163                         object.putInline(exec, identF, jsNumber(i), slot);
164                     }
165                     {
166                         PutPropertySlot slot(object, false, PutPropertySlot::PutById);
167                         object.putInline(exec, identG, jsNumber(i), slot);
168                     }
169                 }
170             });
171
172         // Non-strict dynamic get by id with dynamic store context:
173         object = JSFinalObject::create(*vm, objectStructure);
174         {
175             PutPropertySlot slot(object, false);
176             object.putInline(exec, identF, jsNumber(42), slot);
177         }
178         {
179             PutPropertySlot slot(object, false);
180             object.putInline(exec, identG, jsNumber(43), slot);
181         }
182         benchmarkImpl(
183             "Non Strict Dynamic Get By Id With Dynamic Store Context",
184             1000000,
185             [&] (unsigned iterationCount) {
186                 for (unsigned i = iterationCount; i--;) {
187                     JSValue result = object.get(exec, identF);
188                     CHECK(result == jsNumber(42));
189                     result = object.get(exec, identG);
190                     CHECK(result == jsNumber(43));
191                 }
192             });
193
194         // Non-strict dynamic put by id replace with dynamic store context:
195         object = JSFinalObject::create(*vm, objectStructure);
196         {
197             PutPropertySlot slot(object, false);
198             object.putInline(exec, identF, jsNumber(42), slot);
199         }
200         {
201             PutPropertySlot slot(object, false);
202             object.putInline(exec, identG, jsNumber(43), slot);
203         }
204         benchmarkImpl(
205             "Non Strict Dynamic Put By Id Replace With Dynamic Store Context",
206             1000000,
207             [&] (unsigned iterationCount) {
208                 for (unsigned i = iterationCount; i--;) {
209                     {
210                         PutPropertySlot slot(object, false);
211                         object.putInline(exec, identF, jsNumber(i), slot);
212                     }
213                     {
214                         PutPropertySlot slot(object, false);
215                         object.putInline(exec, identG, jsNumber(i), slot);
216                     }
217                 }
218             });
219
220         // Non-strict dynamic put by id transition with object allocation with dynamic store context:
221         benchmarkImpl(
222             "Non Strict Dynamic Allocation and Put By Id Transition With Dynamic Store Context",
223             1000000,
224             [&] (unsigned iterationCount) {
225                 for (unsigned i = iterationCount; i--;) {
226                     JSValue object = JSFinalObject::create(*vm, objectStructure);
227                     {
228                         PutPropertySlot slot(object, false);
229                         object.putInline(exec, identF, jsNumber(i), slot);
230                     }
231                     {
232                         PutPropertySlot slot(object, false);
233                         object.putInline(exec, identG, jsNumber(i), slot);
234                     }
235                 }
236             });
237     }
238
239     crashLock.lock();
240     return 0;
241 }
242