blob: 16065db8353809e3eee4fcd3d70457bbeac3a9be [file] [log] [blame]
fpizlo@apple.coma0f3bf12015-12-16 22:39:13 +00001/*
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"
fpizlo@apple.com5e29b762016-03-18 00:53:24 +000036#include <wtf/MainThread.h>
fpizlo@apple.coma0f3bf12015-12-16 22:39:13 +000037
38using namespace JSC;
39
40namespace {
41
42StaticLock crashLock;
43const char* nameFilter;
44unsigned 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
54template<typename Callback>
55NEVER_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 double before = monotonicallyIncreasingTimeMS();
64 callback(iterationCount);
65 double after = monotonicallyIncreasingTimeMS();
66 dataLog(name, ": ", after - before, " ms.\n");
67}
68
69} // anonymous namespace
70
71int 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