blob: e7f88c2772884ad30bc62d9be457a638b3c35362 [file] [log] [blame]
oliver@apple.comea771492013-07-25 03:58:38 +00001/*
fpizlo@apple.com72e75cd2017-01-10 23:41:55 +00002 * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
oliver@apple.comea771492013-07-25 03:58:38 +00003 *
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"
fpizlo@apple.com3ce6ab62016-02-18 16:40:25 +000027#include "FTLLowerDFGToB3.h"
oliver@apple.comea771492013-07-25 03:58:38 +000028
29#if ENABLE(FTL_JIT)
30
fpizlo@apple.com48810522015-12-01 04:43:28 +000031#include "AirGenerationContext.h"
32#include "AllowMacroScratchRegisterUsage.h"
fpizlo@apple.com32b30152016-07-19 01:16:24 +000033#include "B3CheckValue.h"
fpizlo@apple.com9a175952016-09-28 21:55:53 +000034#include "B3FenceValue.h"
fpizlo@apple.com32b30152016-07-19 01:16:24 +000035#include "B3PatchpointValue.h"
36#include "B3SlotBaseValue.h"
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +000037#include "B3StackmapGenerationParams.h"
fpizlo@apple.com32b30152016-07-19 01:16:24 +000038#include "B3ValueInlines.h"
fpizlo@apple.coma42de462015-12-22 20:03:13 +000039#include "CallFrameShuffler.h"
oliver@apple.comea771492013-07-25 03:58:38 +000040#include "CodeBlockWithJITType.h"
oliver@apple.com55d32d92013-07-25 04:05:03 +000041#include "DFGAbstractInterpreterInlines.h"
commit-queue@webkit.org91b902c2016-08-20 02:00:44 +000042#include "DFGCapabilities.h"
fpizlo@apple.com92dbc1f2015-11-02 00:48:03 +000043#include "DFGDominators.h"
oliver@apple.com55d32d92013-07-25 04:05:03 +000044#include "DFGInPlaceAbstractState.h"
fpizlo@apple.com9e64b502014-09-16 22:18:23 +000045#include "DFGOSRAvailabilityAnalysisPhase.h"
fpizlo@apple.comf19f0142015-07-03 01:48:01 +000046#include "DFGOSRExitFuzz.h"
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +000047#include "DOMJITPatchpoint.h"
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000048#include "DirectArguments.h"
oliver@apple.comea771492013-07-25 03:58:38 +000049#include "FTLAbstractHeapRepository.h"
msaboff@apple.com95894332014-01-29 19:18:54 +000050#include "FTLAvailableRecovery.h"
utatane.tea@gmail.comad4eb052016-10-07 05:07:13 +000051#include "FTLDOMJITPatchpointParams.h"
fpizlo@apple.com45e45652016-01-07 21:20:37 +000052#include "FTLExceptionTarget.h"
fpizlo@apple.com532f1e52013-09-04 06:26:04 +000053#include "FTLForOSREntryJITCode.h"
oliver@apple.comea771492013-07-25 03:58:38 +000054#include "FTLFormattedValue.h"
fpizlo@apple.com6e697962015-10-12 17:56:26 +000055#include "FTLLazySlowPathCall.h"
oliver@apple.com827d2cf2013-07-25 04:04:45 +000056#include "FTLLoweredNodeValue.h"
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000057#include "FTLOperations.h"
fpizlo@apple.com23ac27a2016-02-18 00:42:36 +000058#include "FTLOutput.h"
fpizlo@apple.com45e45652016-01-07 21:20:37 +000059#include "FTLPatchpointExceptionHandle.h"
oliver@apple.comea771492013-07-25 03:58:38 +000060#include "FTLThunks.h"
fpizlo@apple.com975ae502014-02-19 22:29:43 +000061#include "FTLWeightedTarget.h"
fpizlo@apple.come41ca562016-01-04 21:33:37 +000062#include "JITAddGenerator.h"
fpizlo@apple.comfee31e22016-01-04 22:31:45 +000063#include "JITBitAndGenerator.h"
fpizlo@apple.com905e5722016-01-04 23:08:32 +000064#include "JITBitOrGenerator.h"
65#include "JITBitXorGenerator.h"
fpizlo@apple.come41ca562016-01-04 21:33:37 +000066#include "JITDivGenerator.h"
fpizlo@apple.comef5e13652016-02-18 00:11:21 +000067#include "JITInlineCacheGenerator.h"
fpizlo@apple.com905e5722016-01-04 23:08:32 +000068#include "JITLeftShiftGenerator.h"
sbarati@apple.comb0b1eb52016-07-21 23:41:44 +000069#include "JITMathIC.h"
fpizlo@apple.come41ca562016-01-04 21:33:37 +000070#include "JITMulGenerator.h"
fpizlo@apple.com905e5722016-01-04 23:08:32 +000071#include "JITRightShiftGenerator.h"
fpizlo@apple.comb19cd822016-01-04 20:49:33 +000072#include "JITSubGenerator.h"
fpizlo@apple.comfb7eff22014-02-11 01:45:50 +000073#include "JSCInlines.h"
utatane.tea@gmail.com9d9fd322015-12-17 10:33:08 +000074#include "JSGeneratorFunction.h"
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000075#include "JSLexicalEnvironment.h"
sbarati@apple.com21fc86e2016-09-06 23:22:01 +000076#include "JSMap.h"
fpizlo@apple.comff27eed2014-07-23 04:33:37 +000077#include "OperandsInlines.h"
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000078#include "ScopedArguments.h"
79#include "ScopedArgumentsTable.h"
fpizlo@apple.com6e697962015-10-12 17:56:26 +000080#include "ScratchRegisterAllocator.h"
fpizlo@apple.com203ebdb2015-12-21 18:56:54 +000081#include "SetupVarargsFrame.h"
fpizlo@apple.comd5f99462016-04-11 19:31:04 +000082#include "ShadowChicken.h"
83#include "StructureStubInfo.h"
msaboff@apple.com62aa8b72013-09-26 22:53:54 +000084#include "VirtualRegister.h"
mark.lam@apple.com528ebe92015-08-19 21:18:15 +000085#include "Watchdog.h"
andersca@apple.com99491a22014-01-25 21:16:42 +000086#include <atomic>
peavo@outlook.combdf5f412016-01-12 21:34:29 +000087#if !OS(WINDOWS)
fpizlo@apple.comff27eed2014-07-23 04:33:37 +000088#include <dlfcn.h>
peavo@outlook.combdf5f412016-01-12 21:34:29 +000089#endif
fpizlo@apple.comb1e1c2d2015-05-05 20:42:44 +000090#include <unordered_set>
fpizlo@apple.com91aea582015-12-10 03:50:07 +000091#include <wtf/Box.h>
oliver@apple.com827d2cf2013-07-25 04:04:45 +000092#include <wtf/ProcessID.h>
oliver@apple.comea771492013-07-25 03:58:38 +000093
94namespace JSC { namespace FTL {
95
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +000096using namespace B3;
oliver@apple.comea771492013-07-25 03:58:38 +000097using namespace DFG;
98
fpizlo@apple.coma61e9a82015-06-16 19:17:40 +000099namespace {
100
101std::atomic<int> compileCounter;
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000102
fpizlo@apple.comd3717142016-06-27 23:26:41 +0000103#if !ASSERT_DISABLED
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +0000104NO_RETURN_DUE_TO_CRASH static void ftlUnreachable(
105 CodeBlock* codeBlock, BlockIndex blockIndex, unsigned nodeIndex)
106{
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +0000107 dataLog("Crashing in thought-to-be-unreachable FTL-generated code for ", pointerDump(codeBlock), " at basic block #", blockIndex);
108 if (nodeIndex != UINT_MAX)
109 dataLog(", node @", nodeIndex);
110 dataLog(".\n");
111 CRASH();
112}
113#endif
114
fpizlo@apple.com3ce6ab62016-02-18 16:40:25 +0000115// Using this instead of typeCheck() helps to reduce the load on B3, by creating
oliver@apple.comea771492013-07-25 03:58:38 +0000116// significantly less dead code.
mark.lam@apple.comc0f1f562016-01-22 23:30:07 +0000117#define FTL_TYPE_CHECK_WITH_EXIT_KIND(exitKind, lowValue, highValue, typesPassedThrough, failCondition) do { \
oliver@apple.comea771492013-07-25 03:58:38 +0000118 FormattedValue _ftc_lowValue = (lowValue); \
119 Edge _ftc_highValue = (highValue); \
120 SpeculatedType _ftc_typesPassedThrough = (typesPassedThrough); \
oliver@apple.com55d32d92013-07-25 04:05:03 +0000121 if (!m_interpreter.needsTypeCheck(_ftc_highValue, _ftc_typesPassedThrough)) \
oliver@apple.comea771492013-07-25 03:58:38 +0000122 break; \
mark.lam@apple.comc0f1f562016-01-22 23:30:07 +0000123 typeCheck(_ftc_lowValue, _ftc_highValue, _ftc_typesPassedThrough, (failCondition), exitKind); \
oliver@apple.comea771492013-07-25 03:58:38 +0000124 } while (false)
125
mark.lam@apple.comc0f1f562016-01-22 23:30:07 +0000126#define FTL_TYPE_CHECK(lowValue, highValue, typesPassedThrough, failCondition) \
127 FTL_TYPE_CHECK_WITH_EXIT_KIND(BadType, lowValue, highValue, typesPassedThrough, failCondition)
128
fpizlo@apple.com3ce6ab62016-02-18 16:40:25 +0000129class LowerDFGToB3 {
130 WTF_MAKE_NONCOPYABLE(LowerDFGToB3);
oliver@apple.comea771492013-07-25 03:58:38 +0000131public:
fpizlo@apple.com3ce6ab62016-02-18 16:40:25 +0000132 LowerDFGToB3(State& state)
oliver@apple.comea771492013-07-25 03:58:38 +0000133 : m_graph(state.graph)
134 , m_ftlState(state)
benjamin@webkit.org81ec96c2015-11-18 23:14:54 +0000135 , m_out(state)
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +0000136 , m_proc(*state.proc)
sbarati@apple.come20444a2016-11-30 06:24:44 +0000137 , m_availabilityCalculator(m_graph)
oliver@apple.comea771492013-07-25 03:58:38 +0000138 , m_state(state.graph)
oliver@apple.com55d32d92013-07-25 04:05:03 +0000139 , m_interpreter(state.graph, m_state)
oliver@apple.comea771492013-07-25 03:58:38 +0000140 {
141 }
msaboff@apple.com044ba8d2015-02-18 23:52:16 +0000142
143 void lower()
oliver@apple.comea771492013-07-25 03:58:38 +0000144 {
fpizlo@apple.com45e45652016-01-07 21:20:37 +0000145 State* state = &m_ftlState;
146
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000147 CString name;
148 if (verboseCompilationEnabled()) {
149 name = toCString(
andersca@apple.com99491a22014-01-25 21:16:42 +0000150 "jsBody_", ++compileCounter, "_", codeBlock()->inferredName(),
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000151 "_", codeBlock()->hash());
152 } else
153 name = "jsBody";
154
fpizlo@apple.com92dbc1f2015-11-02 00:48:03 +0000155 m_graph.ensureDominators();
benjamin@webkit.org81ec96c2015-11-18 23:14:54 +0000156
fpizlo@apple.com57399572014-03-05 22:01:57 +0000157 if (verboseCompilationEnabled())
158 dataLog("Function ready, beginning lowering.\n");
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +0000159
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +0000160 m_out.initialize(m_heaps);
fpizlo@apple.comdfff0f22015-12-08 00:02:09 +0000161
162 // We use prologue frequency for all of the initialization code.
163 m_out.setFrequency(1);
oliver@apple.comea771492013-07-25 03:58:38 +0000164
fpizlo@apple.com91331742016-03-07 02:07:28 +0000165 m_prologue = m_out.newBlock();
fpizlo@apple.com91331742016-03-07 02:07:28 +0000166 m_handleExceptions = m_out.newBlock();
msaboff@apple.com95894332014-01-29 19:18:54 +0000167
oliver@apple.com426f5b02013-07-25 04:04:27 +0000168 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
169 m_highBlock = m_graph.block(blockIndex);
oliver@apple.comea771492013-07-25 03:58:38 +0000170 if (!m_highBlock)
171 continue;
fpizlo@apple.comdfff0f22015-12-08 00:02:09 +0000172 m_out.setFrequency(m_highBlock->executionCount);
fpizlo@apple.com91331742016-03-07 02:07:28 +0000173 m_blocks.add(m_highBlock, m_out.newBlock());
oliver@apple.comea771492013-07-25 03:58:38 +0000174 }
fpizlo@apple.comdfff0f22015-12-08 00:02:09 +0000175
176 // Back to prologue frequency for any bocks that get sneakily created in the initialization code.
177 m_out.setFrequency(1);
oliver@apple.comea771492013-07-25 03:58:38 +0000178
commit-queue@webkit.org3d24d902016-05-20 02:37:53 +0000179 m_out.appendTo(m_prologue, m_handleExceptions);
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +0000180 m_out.initializeConstants(m_proc, m_prologue);
msaboff@apple.com95894332014-01-29 19:18:54 +0000181 createPhiVariables();
fpizlo@apple.comff27eed2014-07-23 04:33:37 +0000182
fpizlo@apple.com6c34ef02015-12-15 00:30:53 +0000183 size_t sizeOfCaptured = sizeof(JSValue) * m_graph.m_nextMachineLocal;
fpizlo@apple.com215f8f02016-01-26 22:05:28 +0000184 B3::SlotBaseValue* capturedBase = m_out.lockedStackSlot(sizeOfCaptured);
fpizlo@apple.com6c34ef02015-12-15 00:30:53 +0000185 m_captured = m_out.add(capturedBase, m_out.constIntPtr(sizeOfCaptured));
fpizlo@apple.com215f8f02016-01-26 22:05:28 +0000186 state->capturedValue = capturedBase->slot();
benjamin@webkit.org81ec96c2015-11-18 23:14:54 +0000187
188 auto preOrder = m_graph.blocksInPreOrder();
fpizlo@apple.com203ebdb2015-12-21 18:56:54 +0000189
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +0000190 m_callFrame = m_out.framePointer();
msaboff@apple.com95894332014-01-29 19:18:54 +0000191 m_tagTypeNumber = m_out.constInt64(TagTypeNumber);
192 m_tagMask = m_out.constInt64(TagMask);
fpizlo@apple.com06abfa02015-12-08 02:46:22 +0000193
fpizlo@apple.com06abfa02015-12-08 02:46:22 +0000194 // Make sure that B3 knows that we really care about the mask registers. This forces the
195 // constants to be materialized in registers.
196 m_proc.addFastConstant(m_tagTypeNumber->key());
197 m_proc.addFastConstant(m_tagMask->key());
msaboff@apple.com95894332014-01-29 19:18:54 +0000198
sbarati@apple.com239d20b2017-01-26 23:50:58 +0000199 // We don't want the CodeBlock to have a weak pointer to itself because
200 // that would cause it to always get collected.
201 m_out.storePtr(m_out.constIntPtr(bitwise_cast<intptr_t>(codeBlock())), addressFor(CallFrameSlot::codeBlock));
fpizlo@apple.comdfefc4a2016-01-09 00:37:47 +0000202
commit-queue@webkit.org3d24d902016-05-20 02:37:53 +0000203 // Stack Overflow Check.
204 unsigned exitFrameSize = m_graph.requiredRegisterCountForExit() * sizeof(Register);
mark.lam@apple.comb083d152016-07-12 22:06:20 +0000205 MacroAssembler::AbsoluteAddress addressOfStackLimit(vm().addressOfSoftStackLimit());
commit-queue@webkit.org3d24d902016-05-20 02:37:53 +0000206 PatchpointValue* stackOverflowHandler = m_out.patchpoint(Void);
207 CallSiteIndex callSiteIndex = callSiteIndexForCodeOrigin(m_ftlState, CodeOrigin(0));
208 stackOverflowHandler->appendSomeRegister(m_callFrame);
209 stackOverflowHandler->clobber(RegisterSet::macroScratchRegisters());
210 stackOverflowHandler->numGPScratchRegisters = 1;
211 stackOverflowHandler->setGenerator(
212 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
213 AllowMacroScratchRegisterUsage allowScratch(jit);
214 GPRReg fp = params[0].gpr();
215 GPRReg scratch = params.gpScratch(0);
216
217 unsigned ftlFrameSize = params.proc().frameSize();
218
219 jit.addPtr(MacroAssembler::TrustedImm32(-std::max(exitFrameSize, ftlFrameSize)), fp, scratch);
220 MacroAssembler::Jump stackOverflow = jit.branchPtr(MacroAssembler::Above, addressOfStackLimit, scratch);
221
222 params.addLatePath([=] (CCallHelpers& jit) {
223 AllowMacroScratchRegisterUsage allowScratch(jit);
224
225 stackOverflow.link(&jit);
226 jit.store32(
227 MacroAssembler::TrustedImm32(callSiteIndex.bits()),
mark.lam@apple.com2bd89342016-07-08 22:58:15 +0000228 CCallHelpers::tagFor(VirtualRegister(CallFrameSlot::argumentCount)));
commit-queue@webkit.org3d24d902016-05-20 02:37:53 +0000229 jit.copyCalleeSavesToVMEntryFrameCalleeSavesBuffer();
230
231 jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
232 jit.move(CCallHelpers::TrustedImmPtr(jit.codeBlock()), GPRInfo::argumentGPR1);
233 CCallHelpers::Call throwCall = jit.call();
234
235 jit.move(CCallHelpers::TrustedImmPtr(jit.vm()), GPRInfo::argumentGPR0);
236 jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
237 CCallHelpers::Call lookupExceptionHandlerCall = jit.call();
238 jit.jumpToExceptionHandler();
239
240 jit.addLinkTask(
241 [=] (LinkBuffer& linkBuffer) {
242 linkBuffer.link(throwCall, FunctionPtr(operationThrowStackOverflowError));
243 linkBuffer.link(lookupExceptionHandlerCall, FunctionPtr(lookupExceptionHandlerFromCallerFrame));
fpizlo@apple.comdfefc4a2016-01-09 00:37:47 +0000244 });
commit-queue@webkit.org3d24d902016-05-20 02:37:53 +0000245 });
fpizlo@apple.comdfefc4a2016-01-09 00:37:47 +0000246 });
commit-queue@webkit.org3d24d902016-05-20 02:37:53 +0000247
248 LBasicBlock firstDFGBasicBlock = lowBlock(m_graph.block(0));
249 // Check Arguments.
fpizlo@apple.com064f0812015-02-16 19:27:37 +0000250 availabilityMap().clear();
251 availabilityMap().m_locals = Operands<Availability>(codeBlock()->numParameters(), 0);
252 for (unsigned i = codeBlock()->numParameters(); i--;) {
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +0000253 availabilityMap().m_locals.argument(i) =
254 Availability(FlushedAt(FlushedJSValue, virtualRegisterForArgument(i)));
255 }
256 m_node = nullptr;
257 m_origin = NodeOrigin(CodeOrigin(0), CodeOrigin(0), true);
258 for (unsigned i = codeBlock()->numParameters(); i--;) {
259 Node* node = m_graph.m_arguments[i];
fpizlo@apple.com064f0812015-02-16 19:27:37 +0000260 VirtualRegister operand = virtualRegisterForArgument(i);
261
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +0000262 LValue jsValue = m_out.load64(addressFor(operand));
msaboff@apple.com26000632016-12-12 21:46:45 +0000263
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +0000264 if (node) {
265 DFG_ASSERT(m_graph, node, operand == node->stackAccessData()->machineLocal);
fpizlo@apple.com064f0812015-02-16 19:27:37 +0000266
267 // This is a hack, but it's an effective one. It allows us to do CSE on the
268 // primordial load of arguments. This assumes that the GetLocal that got put in
269 // place of the original SetArgument doesn't have any effects before it. This
270 // should hold true.
271 m_loadedArgumentValues.add(node, jsValue);
272 }
273
274 switch (m_graph.m_argumentFormats[i]) {
275 case FlushedInt32:
276 speculate(BadType, jsValueValue(jsValue), node, isNotInt32(jsValue));
277 break;
278 case FlushedBoolean:
279 speculate(BadType, jsValueValue(jsValue), node, isNotBoolean(jsValue));
280 break;
281 case FlushedCell:
282 speculate(BadType, jsValueValue(jsValue), node, isNotCell(jsValue));
283 break;
284 case FlushedJSValue:
285 break;
286 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +0000287 DFG_CRASH(m_graph, node, "Bad flush format for argument");
fpizlo@apple.com064f0812015-02-16 19:27:37 +0000288 break;
289 }
290 }
commit-queue@webkit.org3d24d902016-05-20 02:37:53 +0000291 m_out.jump(firstDFGBasicBlock);
292
293 m_out.appendTo(m_handleExceptions, firstDFGBasicBlock);
294 Box<CCallHelpers::Label> exceptionHandler = state->exceptionHandler;
295 m_out.patchpoint(Void)->setGenerator(
296 [=] (CCallHelpers& jit, const StackmapGenerationParams&) {
297 CCallHelpers::Jump jump = jit.jump();
298 jit.addLinkTask(
299 [=] (LinkBuffer& linkBuffer) {
300 linkBuffer.link(jump, linkBuffer.locationOf(*exceptionHandler));
301 });
302 });
303 m_out.unreachable();
304
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +0000305 for (DFG::BasicBlock* block : preOrder)
fpizlo@apple.comaa4f4582014-09-09 00:34:40 +0000306 compileBlock(block);
benjamin@webkit.org81ec96c2015-11-18 23:14:54 +0000307
fpizlo@apple.com7a502892016-02-28 20:34:03 +0000308 // Make sure everything is decorated. This does a bunch of deferred decorating. This has
309 // to happen last because our abstract heaps are generated lazily. They have to be
310 // generated lazily because we have an infiniten number of numbered, indexed, and
311 // absolute heaps. We only become aware of the ones we actually mention while lowering.
312 m_heaps.computeRangesAndDecorateInstructions();
313
fpizlo@apple.com959a66a2016-01-05 22:38:11 +0000314 // We create all Phi's up front, but we may then decide not to compile the basic block
315 // that would have contained one of them. So this creates orphans, which triggers B3
316 // validation failures. Calling this fixes the issue.
317 //
318 // Note that you should avoid the temptation to make this call conditional upon
319 // validation being enabled. B3 makes no guarantees of any kind of correctness when
320 // dealing with IR that would have failed validation. For example, it would be valid to
321 // write a B3 phase that so aggressively assumes the lack of orphans that it would crash
322 // if any orphans were around. We might even have such phases already.
323 m_proc.deleteOrphans();
fpizlo@apple.com11aaea92016-01-26 08:17:31 +0000324
325 // We put the blocks into the B3 procedure in a super weird order. Now we reorder them.
326 m_out.applyBlockOrder();
oliver@apple.comea771492013-07-25 03:58:38 +0000327 }
328
329private:
330
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000331 void createPhiVariables()
oliver@apple.comea771492013-07-25 03:58:38 +0000332 {
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000333 for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +0000334 DFG::BasicBlock* block = m_graph.block(blockIndex);
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000335 if (!block)
oliver@apple.comea771492013-07-25 03:58:38 +0000336 continue;
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000337 for (unsigned nodeIndex = block->size(); nodeIndex--;) {
338 Node* node = block->at(nodeIndex);
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +0000339 if (node->op() != DFG::Phi)
oliver@apple.comea771492013-07-25 03:58:38 +0000340 continue;
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000341 LType type;
342 switch (node->flags() & NodeResultMask) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000343 case NodeResultDouble:
fpizlo@apple.com994d4532016-07-03 19:34:55 +0000344 type = Double;
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000345 break;
346 case NodeResultInt32:
fpizlo@apple.com994d4532016-07-03 19:34:55 +0000347 type = Int32;
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000348 break;
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000349 case NodeResultInt52:
fpizlo@apple.com994d4532016-07-03 19:34:55 +0000350 type = Int64;
fpizlo@apple.com6921b292013-09-18 17:14:02 +0000351 break;
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000352 case NodeResultBoolean:
fpizlo@apple.com994d4532016-07-03 19:34:55 +0000353 type = Int32;
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000354 break;
355 case NodeResultJS:
fpizlo@apple.com994d4532016-07-03 19:34:55 +0000356 type = Int64;
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000357 break;
358 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +0000359 DFG_CRASH(m_graph, node, "Bad Phi node result type");
360 break;
oliver@apple.comea771492013-07-25 03:58:38 +0000361 }
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +0000362 m_phis.add(node, m_proc.add<Value>(B3::Phi, type, Origin(node)));
oliver@apple.comea771492013-07-25 03:58:38 +0000363 }
oliver@apple.comea771492013-07-25 03:58:38 +0000364 }
365 }
366
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +0000367 void compileBlock(DFG::BasicBlock* block)
oliver@apple.comea771492013-07-25 03:58:38 +0000368 {
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000369 if (!block)
oliver@apple.comea771492013-07-25 03:58:38 +0000370 return;
371
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000372 if (verboseCompilationEnabled())
373 dataLog("Compiling block ", *block, "\n");
374
375 m_highBlock = block;
376
fpizlo@apple.comdfff0f22015-12-08 00:02:09 +0000377 // Make sure that any blocks created while lowering code in the high block have the frequency of
378 // the high block. This is appropriate because B3 doesn't need precise frequencies. It just needs
379 // something roughly approximate for things like register allocation.
380 m_out.setFrequency(m_highBlock->executionCount);
381
oliver@apple.comea771492013-07-25 03:58:38 +0000382 LBasicBlock lowBlock = m_blocks.get(m_highBlock);
383
384 m_nextHighBlock = 0;
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000385 for (BlockIndex nextBlockIndex = m_highBlock->index + 1; nextBlockIndex < m_graph.numBlocks(); ++nextBlockIndex) {
oliver@apple.com426f5b02013-07-25 04:04:27 +0000386 m_nextHighBlock = m_graph.block(nextBlockIndex);
oliver@apple.comea771492013-07-25 03:58:38 +0000387 if (m_nextHighBlock)
388 break;
389 }
390 m_nextLowBlock = m_nextHighBlock ? m_blocks.get(m_nextHighBlock) : 0;
391
392 // All of this effort to find the next block gives us the ability to keep the
393 // generated IR in roughly program order. This ought not affect the performance
fpizlo@apple.com3ce6ab62016-02-18 16:40:25 +0000394 // of the generated code (since we expect B3 to reorder things) but it will
oliver@apple.comea771492013-07-25 03:58:38 +0000395 // make IR dumps easier to read.
396 m_out.appendTo(lowBlock, m_nextLowBlock);
397
fpizlo@apple.com532f1e52013-09-04 06:26:04 +0000398 if (Options::ftlCrashes())
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +0000399 m_out.trap();
fpizlo@apple.com532f1e52013-09-04 06:26:04 +0000400
oliver@apple.com6a2aafd2013-07-25 04:03:56 +0000401 if (!m_highBlock->cfaHasVisited) {
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +0000402 if (verboseCompilationEnabled())
403 dataLog("Bailing because CFA didn't reach.\n");
fpizlo@apple.comd3717142016-06-27 23:26:41 +0000404 crash(m_highBlock, nullptr);
oliver@apple.com6a2aafd2013-07-25 04:03:56 +0000405 return;
406 }
407
fpizlo@apple.com9e64b502014-09-16 22:18:23 +0000408 m_availabilityCalculator.beginBlock(m_highBlock);
oliver@apple.comea771492013-07-25 03:58:38 +0000409
oliver@apple.comea771492013-07-25 03:58:38 +0000410 m_state.reset();
411 m_state.beginBasicBlock(m_highBlock);
412
oliver@apple.com0d018be2013-07-25 04:00:02 +0000413 for (m_nodeIndex = 0; m_nodeIndex < m_highBlock->size(); ++m_nodeIndex) {
414 if (!compileNode(m_nodeIndex))
415 break;
416 }
oliver@apple.comea771492013-07-25 03:58:38 +0000417 }
msaboff@apple.com3fdcb112015-02-01 03:58:39 +0000418
419 void safelyInvalidateAfterTermination()
420 {
421 if (verboseCompilationEnabled())
422 dataLog("Bailing.\n");
fpizlo@apple.com1617af22015-02-03 00:43:25 +0000423 crash();
msaboff@apple.com3fdcb112015-02-01 03:58:39 +0000424
425 // Invalidate dominated blocks. Under normal circumstances we would expect
426 // them to be invalidated already. But you can have the CFA become more
427 // precise over time because the structures of objects change on the main
428 // thread. Failing to do this would result in weird crashes due to a value
429 // being used but not defined. Race conditions FTW!
430 for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +0000431 DFG::BasicBlock* target = m_graph.block(blockIndex);
msaboff@apple.com3fdcb112015-02-01 03:58:39 +0000432 if (!target)
433 continue;
fpizlo@apple.com92dbc1f2015-11-02 00:48:03 +0000434 if (m_graph.m_dominators->dominates(m_highBlock, target)) {
msaboff@apple.com3fdcb112015-02-01 03:58:39 +0000435 if (verboseCompilationEnabled())
436 dataLog("Block ", *target, " will bail also.\n");
437 target->cfaHasVisited = false;
438 }
439 }
440 }
441
oliver@apple.com0d018be2013-07-25 04:00:02 +0000442 bool compileNode(unsigned nodeIndex)
oliver@apple.comea771492013-07-25 03:58:38 +0000443 {
oliver@apple.com0d018be2013-07-25 04:00:02 +0000444 if (!m_state.isValid()) {
msaboff@apple.com3fdcb112015-02-01 03:58:39 +0000445 safelyInvalidateAfterTermination();
oliver@apple.com0d018be2013-07-25 04:00:02 +0000446 return false;
447 }
448
oliver@apple.comea771492013-07-25 03:58:38 +0000449 m_node = m_highBlock->at(nodeIndex);
fpizlo@apple.comf29186e2015-08-26 19:24:41 +0000450 m_origin = m_node->origin;
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +0000451 m_out.setOrigin(m_node);
oliver@apple.comea771492013-07-25 03:58:38 +0000452
453 if (verboseCompilationEnabled())
454 dataLog("Lowering ", m_node, "\n");
455
msaboff@apple.com95894332014-01-29 19:18:54 +0000456 m_availableRecoveries.resize(0);
457
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +0000458 m_interpreter.startExecuting();
fpizlo@apple.come237cef2016-04-26 17:38:43 +0000459 m_interpreter.executeKnownEdgeTypes(m_node);
oliver@apple.comea771492013-07-25 03:58:38 +0000460
oliver@apple.comea771492013-07-25 03:58:38 +0000461 switch (m_node->op()) {
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +0000462 case DFG::Upsilon:
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000463 compileUpsilon();
464 break;
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +0000465 case DFG::Phi:
oliver@apple.com827d2cf2013-07-25 04:04:45 +0000466 compilePhi();
467 break;
oliver@apple.comea771492013-07-25 03:58:38 +0000468 case JSConstant:
oliver@apple.comea771492013-07-25 03:58:38 +0000469 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000470 case DoubleConstant:
471 compileDoubleConstant();
472 break;
473 case Int52Constant:
474 compileInt52Constant();
475 break;
fpizlo@apple.com024424c2016-03-09 05:16:47 +0000476 case LazyJSConstant:
477 compileLazyJSConstant();
478 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000479 case DoubleRep:
480 compileDoubleRep();
481 break;
benjamin@webkit.orgcb584082015-05-08 00:23:32 +0000482 case DoubleAsInt32:
483 compileDoubleAsInt32();
484 break;
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +0000485 case DFG::ValueRep:
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +0000486 compileValueRep();
487 break;
488 case Int52Rep:
489 compileInt52Rep();
490 break;
491 case ValueToInt32:
492 compileValueToInt32();
493 break;
fpizlo@apple.com96509b72014-05-26 17:43:41 +0000494 case BooleanToNumber:
495 compileBooleanToNumber();
496 break;
fpizlo@apple.com532f1e52013-09-04 06:26:04 +0000497 case ExtractOSREntryLocal:
498 compileExtractOSREntryLocal();
499 break;
fpizlo@apple.combcfd8eb2015-02-26 19:51:52 +0000500 case GetStack:
501 compileGetStack();
oliver@apple.comea771492013-07-25 03:58:38 +0000502 break;
fpizlo@apple.combcfd8eb2015-02-26 19:51:52 +0000503 case PutStack:
504 compilePutStack();
oliver@apple.comea771492013-07-25 03:58:38 +0000505 break;
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +0000506 case DFG::Check:
fpizlo@apple.com163291d2015-04-28 19:27:23 +0000507 compileNoOp();
oliver@apple.comea771492013-07-25 03:58:38 +0000508 break;
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +0000509 case CallObjectConstructor:
510 compileCallObjectConstructor();
511 break;
fpizlo@apple.com763818c2014-02-11 02:41:46 +0000512 case ToThis:
513 compileToThis();
514 break;
oliver@apple.comea771492013-07-25 03:58:38 +0000515 case ValueAdd:
fpizlo@apple.com97756552014-01-02 20:15:25 +0000516 compileValueAdd();
517 break;
fpizlo@apple.comb3b187c2015-08-22 18:35:47 +0000518 case StrCat:
519 compileStrCat();
520 break;
fpizlo@apple.com97756552014-01-02 20:15:25 +0000521 case ArithAdd:
oliver@apple.comea771492013-07-25 03:58:38 +0000522 case ArithSub:
msaboff@apple.com95894332014-01-29 19:18:54 +0000523 compileArithAddOrSub();
oliver@apple.comea771492013-07-25 03:58:38 +0000524 break;
benjamin@webkit.orge324d432015-04-26 19:55:18 +0000525 case ArithClz32:
526 compileArithClz32();
527 break;
oliver@apple.comea771492013-07-25 03:58:38 +0000528 case ArithMul:
529 compileArithMul();
530 break;
oliver@apple.comdd372b72013-07-25 04:01:08 +0000531 case ArithDiv:
msaboff@apple.com95894332014-01-29 19:18:54 +0000532 compileArithDiv();
oliver@apple.comdd372b72013-07-25 04:01:08 +0000533 break;
oliver@apple.comd533b1832013-07-25 04:01:22 +0000534 case ArithMod:
msaboff@apple.com95894332014-01-29 19:18:54 +0000535 compileArithMod();
oliver@apple.comd533b1832013-07-25 04:01:22 +0000536 break;
oliver@apple.com61cccb82013-07-25 04:01:30 +0000537 case ArithMin:
538 case ArithMax:
539 compileArithMinOrMax();
540 break;
oliver@apple.com0452e562013-07-25 04:01:40 +0000541 case ArithAbs:
542 compileArithAbs();
543 break;
msaboff@apple.com95894332014-01-29 19:18:54 +0000544 case ArithSin:
545 compileArithSin();
546 break;
547 case ArithCos:
548 compileArithCos();
549 break;
utatane.tea@gmail.com9917d6a2016-09-12 22:01:13 +0000550 case ArithTan:
551 compileArithTan();
552 break;
benjamin@webkit.org903025b2015-02-14 04:20:21 +0000553 case ArithPow:
554 compileArithPow();
555 break;
utatane.tea@gmail.comd2fca0a2015-12-15 03:51:42 +0000556 case ArithRandom:
557 compileArithRandom();
558 break;
benjamin@webkit.orgcb584082015-05-08 00:23:32 +0000559 case ArithRound:
560 compileArithRound();
561 break;
utatane.tea@gmail.com9971c632016-03-01 02:30:46 +0000562 case ArithFloor:
563 compileArithFloor();
564 break;
565 case ArithCeil:
566 compileArithCeil();
567 break;
utatane.tea@gmail.com9b9f43e2016-04-03 08:37:26 +0000568 case ArithTrunc:
569 compileArithTrunc();
570 break;
msaboff@apple.com95894332014-01-29 19:18:54 +0000571 case ArithSqrt:
572 compileArithSqrt();
573 break;
benjamin@webkit.org2b5682d2015-03-04 22:39:28 +0000574 case ArithLog:
575 compileArithLog();
576 break;
fpizlo@apple.comc5919412014-04-12 23:01:33 +0000577 case ArithFRound:
578 compileArithFRound();
579 break;
oliver@apple.comea771492013-07-25 03:58:38 +0000580 case ArithNegate:
581 compileArithNegate();
582 break;
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +0000583 case DFG::BitAnd:
oliver@apple.comea771492013-07-25 03:58:38 +0000584 compileBitAnd();
585 break;
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +0000586 case DFG::BitOr:
oliver@apple.comea771492013-07-25 03:58:38 +0000587 compileBitOr();
588 break;
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +0000589 case DFG::BitXor:
oliver@apple.comea771492013-07-25 03:58:38 +0000590 compileBitXor();
591 break;
592 case BitRShift:
593 compileBitRShift();
594 break;
595 case BitLShift:
596 compileBitLShift();
597 break;
598 case BitURShift:
599 compileBitURShift();
600 break;
601 case UInt32ToNumber:
602 compileUInt32ToNumber();
603 break;
604 case CheckStructure:
605 compileCheckStructure();
606 break;
fpizlo@apple.com29abafe2014-08-28 19:09:48 +0000607 case CheckCell:
608 compileCheckCell();
fpizlo@apple.comfb813db2013-11-07 05:38:16 +0000609 break;
rniwa@webkit.orgeb7ac192015-03-13 01:11:15 +0000610 case CheckNotEmpty:
611 compileCheckNotEmpty();
612 break;
fpizlo@apple.com29abafe2014-08-28 19:09:48 +0000613 case CheckBadCell:
614 compileCheckBadCell();
615 break;
utatane.tea@gmail.com7f364f22016-07-29 07:15:01 +0000616 case CheckStringIdent:
617 compileCheckStringIdent();
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +0000618 break;
fpizlo@apple.com29abafe2014-08-28 19:09:48 +0000619 case GetExecutable:
620 compileGetExecutable();
msaboff@apple.com95894332014-01-29 19:18:54 +0000621 break;
oliver@apple.comb0cdcb42013-07-25 04:03:57 +0000622 case ArrayifyToStructure:
623 compileArrayifyToStructure();
624 break;
oliver@apple.comea771492013-07-25 03:58:38 +0000625 case PutStructure:
626 compilePutStructure();
627 break;
keith_miller@apple.com7deaba82016-04-10 03:38:44 +0000628 case TryGetById:
cdumez@apple.comc412c1d2016-11-11 16:50:57 +0000629 compileGetById(AccessType::GetPure);
keith_miller@apple.com7deaba82016-04-10 03:38:44 +0000630 break;
fpizlo@apple.com6cd705d2013-10-14 18:08:11 +0000631 case GetById:
sbarati@apple.com5b59c5b2015-10-21 21:49:08 +0000632 case GetByIdFlush:
keith_miller@apple.com7deaba82016-04-10 03:38:44 +0000633 compileGetById(AccessType::Get);
fpizlo@apple.com6cd705d2013-10-14 18:08:11 +0000634 break;
sbarati@apple.com23315d62016-05-09 20:17:23 +0000635 case GetByIdWithThis:
636 compileGetByIdWithThis();
637 break;
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000638 case In:
639 compileIn();
640 break;
sbarati@apple.coma3db4652016-09-20 01:05:50 +0000641 case HasOwnProperty:
642 compileHasOwnProperty();
643 break;
fpizlo@apple.com87839ab2013-11-05 18:56:06 +0000644 case PutById:
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000645 case PutByIdDirect:
sbarati@apple.com5b59c5b2015-10-21 21:49:08 +0000646 case PutByIdFlush:
fpizlo@apple.com87839ab2013-11-05 18:56:06 +0000647 compilePutById();
648 break;
sbarati@apple.com23315d62016-05-09 20:17:23 +0000649 case PutByIdWithThis:
650 compilePutByIdWithThis();
651 break;
utatane.tea@gmail.com287d64c2015-10-27 07:00:57 +0000652 case PutGetterById:
653 case PutSetterById:
654 compilePutAccessorById();
655 break;
656 case PutGetterSetterById:
657 compilePutGetterSetterById();
658 break;
659 case PutGetterByVal:
660 case PutSetterByVal:
661 compilePutAccessorByVal();
662 break;
oliver@apple.comea771492013-07-25 03:58:38 +0000663 case GetButterfly:
664 compileGetButterfly();
665 break;
fpizlo@apple.com9ca951e2013-12-09 01:08:53 +0000666 case ConstantStoragePointer:
667 compileConstantStoragePointer();
668 break;
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +0000669 case GetIndexedPropertyStorage:
670 compileGetIndexedPropertyStorage();
671 break;
672 case CheckArray:
673 compileCheckArray();
674 break;
oliver@apple.comea771492013-07-25 03:58:38 +0000675 case GetArrayLength:
676 compileGetArrayLength();
677 break;
fpizlo@apple.com8624c4b2013-12-10 03:24:31 +0000678 case CheckInBounds:
679 compileCheckInBounds();
680 break;
oliver@apple.comea771492013-07-25 03:58:38 +0000681 case GetByVal:
682 compileGetByVal();
683 break;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000684 case GetMyArgumentByVal:
fpizlo@apple.comc2b8c092016-04-24 17:05:51 +0000685 case GetMyArgumentByValOutOfBounds:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000686 compileGetMyArgumentByVal();
687 break;
sbarati@apple.com23315d62016-05-09 20:17:23 +0000688 case GetByValWithThis:
689 compileGetByValWithThis();
690 break;
oliver@apple.com5b4f1422013-07-25 04:03:54 +0000691 case PutByVal:
692 case PutByValAlias:
fpizlo@apple.com66421ea2013-12-06 22:54:02 +0000693 case PutByValDirect:
oliver@apple.com5b4f1422013-07-25 04:03:54 +0000694 compilePutByVal();
695 break;
sbarati@apple.com23315d62016-05-09 20:17:23 +0000696 case PutByValWithThis:
697 compilePutByValWithThis();
698 break;
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +0000699 case DefineDataProperty:
700 compileDefineDataProperty();
701 break;
702 case DefineAccessorProperty:
703 compileDefineAccessorProperty();
704 break;
fpizlo@apple.com85ab8b52014-01-30 07:30:24 +0000705 case ArrayPush:
706 compileArrayPush();
707 break;
708 case ArrayPop:
709 compileArrayPop();
710 break;
sbarati@apple.comfd407a52017-01-13 04:03:47 +0000711 case ArraySlice:
712 compileArraySlice();
713 break;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000714 case CreateActivation:
715 compileCreateActivation();
716 break;
717 case NewFunction:
utatane.tea@gmail.com9d9fd322015-12-17 10:33:08 +0000718 case NewGeneratorFunction:
caitp@igalia.com8bc562d2016-11-14 21:14:15 +0000719 case NewAsyncFunction:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000720 compileNewFunction();
721 break;
722 case CreateDirectArguments:
723 compileCreateDirectArguments();
724 break;
725 case CreateScopedArguments:
726 compileCreateScopedArguments();
727 break;
728 case CreateClonedArguments:
729 compileCreateClonedArguments();
730 break;
fpizlo@apple.com1002a1d2013-11-06 04:40:02 +0000731 case NewObject:
732 compileNewObject();
733 break;
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +0000734 case NewArray:
735 compileNewArray();
736 break;
sbarati@apple.com99ed4792016-11-12 02:58:11 +0000737 case NewArrayWithSpread:
738 compileNewArrayWithSpread();
739 break;
740 case Spread:
741 compileSpread();
742 break;
fpizlo@apple.comae909c12013-11-09 00:42:05 +0000743 case NewArrayBuffer:
744 compileNewArrayBuffer();
745 break;
msaboff@apple.com95894332014-01-29 19:18:54 +0000746 case NewArrayWithSize:
747 compileNewArrayWithSize();
748 break;
fpizlo@apple.com3bbf1b92016-02-17 04:25:57 +0000749 case NewTypedArray:
750 compileNewTypedArray();
751 break;
commit-queue@webkit.org4b4fe042014-02-03 21:51:47 +0000752 case GetTypedArrayByteOffset:
753 compileGetTypedArrayByteOffset();
754 break;
fpizlo@apple.come962af32013-11-09 01:44:56 +0000755 case AllocatePropertyStorage:
756 compileAllocatePropertyStorage();
757 break;
commit-queue@webkit.org7cd99852014-02-11 01:31:41 +0000758 case ReallocatePropertyStorage:
759 compileReallocatePropertyStorage();
760 break;
fpizlo@apple.comb0e7f3d2016-12-10 01:22:15 +0000761 case NukeStructureAndSetButterfly:
762 compileNukeStructureAndSetButterfly();
763 break;
utatane.tea@gmail.comdb32c542016-06-30 15:26:47 +0000764 case ToNumber:
765 compileToNumber();
766 break;
msaboff@apple.com95894332014-01-29 19:18:54 +0000767 case ToString:
utatane.tea@gmail.com153559e2015-04-06 19:07:12 +0000768 case CallStringConstructor:
769 compileToStringOrCallStringConstructor();
msaboff@apple.com95894332014-01-29 19:18:54 +0000770 break;
fpizlo@apple.com6e550a42014-02-17 20:23:34 +0000771 case ToPrimitive:
772 compileToPrimitive();
773 break;
msaboff@apple.com95894332014-01-29 19:18:54 +0000774 case MakeRope:
775 compileMakeRope();
776 break;
fpizlo@apple.com1d2175a2013-11-06 04:38:23 +0000777 case StringCharAt:
778 compileStringCharAt();
779 break;
fpizlo@apple.comfa2eb272013-11-06 16:38:45 +0000780 case StringCharCodeAt:
781 compileStringCharCodeAt();
782 break;
fpizlo@apple.com47c16d72016-02-16 19:12:36 +0000783 case StringFromCharCode:
784 compileStringFromCharCode();
785 break;
oliver@apple.comea771492013-07-25 03:58:38 +0000786 case GetByOffset:
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000787 case GetGetterSetterByOffset:
oliver@apple.comea771492013-07-25 03:58:38 +0000788 compileGetByOffset();
789 break;
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +0000790 case GetGetter:
791 compileGetGetter();
792 break;
793 case GetSetter:
794 compileGetSetter();
795 break;
fpizlo@apple.com51614cc2014-02-17 06:35:32 +0000796 case MultiGetByOffset:
797 compileMultiGetByOffset();
798 break;
oliver@apple.comea771492013-07-25 03:58:38 +0000799 case PutByOffset:
800 compilePutByOffset();
801 break;
fpizlo@apple.com43219522014-02-25 02:02:50 +0000802 case MultiPutByOffset:
803 compileMultiPutByOffset();
804 break;
oliver@apple.comea771492013-07-25 03:58:38 +0000805 case GetGlobalVar:
saambarati1@gmail.com060e7512015-09-03 19:45:44 +0000806 case GetGlobalLexicalVariable:
807 compileGetGlobalVariable();
oliver@apple.comea771492013-07-25 03:58:38 +0000808 break;
saambarati1@gmail.com060e7512015-09-03 19:45:44 +0000809 case PutGlobalVariable:
810 compilePutGlobalVariable();
oliver@apple.comea771492013-07-25 03:58:38 +0000811 break;
fpizlo@apple.com86468342013-11-27 02:47:43 +0000812 case NotifyWrite:
813 compileNotifyWrite();
fpizlo@apple.com33961712013-11-20 05:49:05 +0000814 break;
msaboff@apple.com95894332014-01-29 19:18:54 +0000815 case GetCallee:
816 compileGetCallee();
817 break;
keith_miller@apple.com85aeabb2016-06-03 23:06:39 +0000818 case GetArgumentCountIncludingThis:
819 compileGetArgumentCountIncludingThis();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000820 break;
msaboff@apple.com95894332014-01-29 19:18:54 +0000821 case GetScope:
822 compileGetScope();
823 break;
fpizlo@apple.com0d5b2e82013-09-08 03:24:13 +0000824 case SkipScope:
825 compileSkipScope();
826 break;
fpizlo@apple.com7518ba22016-03-06 20:11:09 +0000827 case GetGlobalObject:
828 compileGetGlobalObject();
829 break;
fpizlo@apple.com0d5b2e82013-09-08 03:24:13 +0000830 case GetClosureVar:
831 compileGetClosureVar();
832 break;
833 case PutClosureVar:
834 compilePutClosureVar();
835 break;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000836 case GetFromArguments:
837 compileGetFromArguments();
838 break;
839 case PutToArguments:
840 compilePutToArguments();
841 break;
utatane.tea@gmail.combebf7852016-11-10 06:34:05 +0000842 case GetArgument:
843 compileGetArgument();
844 break;
oliver@apple.comea771492013-07-25 03:58:38 +0000845 case CompareEq:
846 compileCompareEq();
847 break;
oliver@apple.com023d1c72013-07-25 03:59:57 +0000848 case CompareStrictEq:
849 compileCompareStrictEq();
850 break;
oliver@apple.comea771492013-07-25 03:58:38 +0000851 case CompareLess:
852 compileCompareLess();
853 break;
oliver@apple.com1f9b9b72013-07-25 03:59:52 +0000854 case CompareLessEq:
855 compileCompareLessEq();
856 break;
857 case CompareGreater:
858 compileCompareGreater();
859 break;
860 case CompareGreaterEq:
861 compileCompareGreaterEq();
862 break;
fpizlo@apple.com4077f612016-07-18 19:12:57 +0000863 case CompareEqPtr:
864 compileCompareEqPtr();
865 break;
oliver@apple.com4965ebc2013-07-25 03:59:53 +0000866 case LogicalNot:
867 compileLogicalNot();
868 break;
fpizlo@apple.comfa258dc2013-09-07 05:47:57 +0000869 case Call:
msaboff@apple.comcdd479b2015-09-30 22:28:08 +0000870 case TailCallInlinedCaller:
fpizlo@apple.comfa258dc2013-09-07 05:47:57 +0000871 case Construct:
872 compileCallOrConstruct();
873 break;
fpizlo@apple.comf0b30cb2016-10-18 18:30:05 +0000874 case DirectCall:
875 case DirectTailCallInlinedCaller:
876 case DirectConstruct:
877 case DirectTailCall:
878 compileDirectCallOrConstruct();
879 break;
msaboff@apple.comcdd479b2015-09-30 22:28:08 +0000880 case TailCall:
881 compileTailCall();
882 break;
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +0000883 case CallVarargs:
884 case CallForwardVarargs:
msaboff@apple.comcdd479b2015-09-30 22:28:08 +0000885 case TailCallVarargs:
886 case TailCallVarargsInlinedCaller:
887 case TailCallForwardVarargs:
888 case TailCallForwardVarargsInlinedCaller:
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +0000889 case ConstructVarargs:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000890 case ConstructForwardVarargs:
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +0000891 compileCallOrConstructVarargs();
892 break;
fpizlo@apple.com48bf58d2016-07-18 19:32:34 +0000893 case CallEval:
894 compileCallEval();
895 break;
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +0000896 case LoadVarargs:
897 compileLoadVarargs();
898 break;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000899 case ForwardVarargs:
900 compileForwardVarargs();
901 break;
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +0000902 case DFG::Jump:
oliver@apple.com0d018be2013-07-25 04:00:02 +0000903 compileJump();
904 break;
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +0000905 case DFG::Branch:
oliver@apple.comea771492013-07-25 03:58:38 +0000906 compileBranch();
907 break;
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +0000908 case DFG::Switch:
oliver@apple.com9f4a6722013-07-25 04:03:05 +0000909 compileSwitch();
910 break;
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +0000911 case DFG::Return:
oliver@apple.com0d018be2013-07-25 04:00:02 +0000912 compileReturn();
913 break;
914 case ForceOSRExit:
915 compileForceOSRExit();
916 break;
fpizlo@apple.come079bb52014-03-05 07:41:03 +0000917 case Throw:
utatane.tea@gmail.com0eb0f832016-10-06 07:44:23 +0000918 case ThrowStaticError:
fpizlo@apple.come079bb52014-03-05 07:41:03 +0000919 compileThrow();
920 break;
fpizlo@apple.comd84425d2013-10-30 19:58:08 +0000921 case InvalidationPoint:
922 compileInvalidationPoint();
923 break;
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +0000924 case IsEmpty:
925 compileIsEmpty();
926 break;
fpizlo@apple.com40750682014-03-13 22:18:50 +0000927 case IsUndefined:
928 compileIsUndefined();
929 break;
930 case IsBoolean:
931 compileIsBoolean();
932 break;
933 case IsNumber:
934 compileIsNumber();
935 break;
utatane.tea@gmail.com4a748b12016-09-17 06:32:50 +0000936 case IsCellWithType:
937 compileIsCellWithType();
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +0000938 break;
sbarati@apple.com21fc86e2016-09-06 23:22:01 +0000939 case MapHash:
940 compileMapHash();
941 break;
942 case GetMapBucket:
943 compileGetMapBucket();
944 break;
945 case LoadFromJSMapBucket:
946 compileLoadFromJSMapBucket();
947 break;
948 case IsNonEmptyMapBucket:
949 compileIsNonEmptyMapBucket();
950 break;
fpizlo@apple.com40750682014-03-13 22:18:50 +0000951 case IsObject:
952 compileIsObject();
953 break;
utatane.tea@gmail.com0bfb74c2015-02-24 23:01:58 +0000954 case IsObjectOrNull:
955 compileIsObjectOrNull();
956 break;
fpizlo@apple.com40750682014-03-13 22:18:50 +0000957 case IsFunction:
958 compileIsFunction();
959 break;
keith_miller@apple.com6919bc12016-06-23 01:39:01 +0000960 case IsTypedArrayView:
961 compileIsTypedArrayView();
962 break;
fpizlo@apple.comb8823d52015-05-03 00:15:27 +0000963 case TypeOf:
964 compileTypeOf();
965 break;
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +0000966 case CheckTypeInfoFlags:
967 compileCheckTypeInfoFlags();
968 break;
969 case OverridesHasInstance:
970 compileOverridesHasInstance();
fpizlo@apple.com44239d42014-03-16 06:02:43 +0000971 break;
972 case InstanceOf:
973 compileInstanceOf();
974 break;
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +0000975 case InstanceOfCustom:
976 compileInstanceOfCustom();
977 break;
msaboff@apple.com95894332014-01-29 19:18:54 +0000978 case CountExecution:
979 compileCountExecution();
980 break;
mhahnenberg@apple.com72454da2014-01-03 00:24:14 +0000981 case StoreBarrier:
fpizlo@apple.com9a175952016-09-28 21:55:53 +0000982 case FencedStoreBarrier:
mhahnenberg@apple.com72454da2014-01-03 00:24:14 +0000983 compileStoreBarrier();
984 break;
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000985 case HasIndexedProperty:
986 compileHasIndexedProperty();
987 break;
988 case HasGenericProperty:
989 compileHasGenericProperty();
990 break;
991 case HasStructureProperty:
992 compileHasStructureProperty();
993 break;
994 case GetDirectPname:
995 compileGetDirectPname();
996 break;
997 case GetEnumerableLength:
998 compileGetEnumerableLength();
999 break;
msaboff@apple.comb644c252015-03-24 10:05:21 +00001000 case GetPropertyEnumerator:
1001 compileGetPropertyEnumerator();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001002 break;
msaboff@apple.comb644c252015-03-24 10:05:21 +00001003 case GetEnumeratorStructurePname:
1004 compileGetEnumeratorStructurePname();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001005 break;
msaboff@apple.comb644c252015-03-24 10:05:21 +00001006 case GetEnumeratorGenericPname:
1007 compileGetEnumeratorGenericPname();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001008 break;
1009 case ToIndexString:
1010 compileToIndexString();
1011 break;
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00001012 case CheckStructureImmediate:
1013 compileCheckStructureImmediate();
1014 break;
1015 case MaterializeNewObject:
1016 compileMaterializeNewObject();
1017 break;
basile_clement@apple.com2ca1f7b2015-05-05 16:34:21 +00001018 case MaterializeCreateActivation:
1019 compileMaterializeCreateActivation();
1020 break;
mark.lam@apple.com528ebe92015-08-19 21:18:15 +00001021 case CheckWatchdogTimer:
1022 compileCheckWatchdogTimer();
1023 break;
sbarati@apple.com6cfefd82016-08-13 02:14:42 +00001024 case CreateRest:
1025 compileCreateRest();
sbarati@apple.comc0722da2015-11-20 02:37:47 +00001026 break;
sbarati@apple.com855d5602015-11-30 20:36:54 +00001027 case GetRestLength:
1028 compileGetRestLength();
1029 break;
fpizlo@apple.comdbd768a2016-02-29 18:05:17 +00001030 case RegExpExec:
1031 compileRegExpExec();
1032 break;
1033 case RegExpTest:
1034 compileRegExpTest();
1035 break;
1036 case NewRegexp:
1037 compileNewRegexp();
1038 break;
mark.lam@apple.com47c2f142016-03-16 18:16:32 +00001039 case SetFunctionName:
1040 compileSetFunctionName();
1041 break;
fpizlo@apple.come799b862016-03-01 21:18:42 +00001042 case StringReplace:
msaboff@apple.com69940442016-04-27 01:28:03 +00001043 case StringReplaceRegExp:
fpizlo@apple.come799b862016-03-01 21:18:42 +00001044 compileStringReplace();
1045 break;
fpizlo@apple.comef515142016-03-04 06:36:24 +00001046 case GetRegExpObjectLastIndex:
1047 compileGetRegExpObjectLastIndex();
1048 break;
1049 case SetRegExpObjectLastIndex:
1050 compileSetRegExpObjectLastIndex();
1051 break;
fpizlo@apple.com39303e02016-04-05 22:17:35 +00001052 case LogShadowChickenPrologue:
1053 compileLogShadowChickenPrologue();
1054 break;
1055 case LogShadowChickenTail:
1056 compileLogShadowChickenTail();
1057 break;
fpizlo@apple.com280ef002016-04-05 22:13:16 +00001058 case RecordRegExpCachedResult:
1059 compileRecordRegExpCachedResult();
1060 break;
sbarati@apple.come67fd782016-04-19 01:38:30 +00001061 case ResolveScope:
1062 compileResolveScope();
1063 break;
1064 case GetDynamicVar:
1065 compileGetDynamicVar();
1066 break;
1067 case PutDynamicVar:
1068 compilePutDynamicVar();
1069 break;
fpizlo@apple.comadbf11d2016-06-10 19:56:18 +00001070 case Unreachable:
1071 compileUnreachable();
1072 break;
sbarati@apple.com527ebc22016-10-05 06:16:15 +00001073 case ToLowerCase:
1074 compileToLowerCase();
1075 break;
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +00001076 case CheckDOM:
1077 compileCheckDOM();
1078 break;
utatane.tea@gmail.com0d74c7c2016-11-03 03:20:53 +00001079 case CallDOM:
1080 compileCallDOM();
1081 break;
utatane.tea@gmail.comc9d8f862016-10-28 22:57:10 +00001082 case CallDOMGetter:
1083 compileCallDOMGetter();
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +00001084 break;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001085
fpizlo@apple.comce995b22013-12-08 19:01:17 +00001086 case PhantomLocal:
fpizlo@apple.comce995b22013-12-08 19:01:17 +00001087 case LoopHint:
fpizlo@apple.com9e64b502014-09-16 22:18:23 +00001088 case MovHint:
1089 case ZombieHint:
fpizlo@apple.comf29186e2015-08-26 19:24:41 +00001090 case ExitOK:
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00001091 case PhantomNewObject:
commit-queue@webkit.org88ab4e72015-04-24 02:23:36 +00001092 case PhantomNewFunction:
utatane.tea@gmail.com9d9fd322015-12-17 10:33:08 +00001093 case PhantomNewGeneratorFunction:
caitp@igalia.com8bc562d2016-11-14 21:14:15 +00001094 case PhantomNewAsyncFunction:
basile_clement@apple.com2ca1f7b2015-05-05 16:34:21 +00001095 case PhantomCreateActivation:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001096 case PhantomDirectArguments:
sbarati@apple.com7a74ce72016-11-01 20:03:03 +00001097 case PhantomCreateRest:
sbarati@apple.come20444a2016-11-30 06:24:44 +00001098 case PhantomSpread:
1099 case PhantomNewArrayWithSpread:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001100 case PhantomClonedArguments:
fpizlo@apple.com8ff74712015-03-17 15:50:44 +00001101 case PutHint:
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00001102 case BottomValue:
fpizlo@apple.combcfd8eb2015-02-26 19:51:52 +00001103 case KillStack:
fpizlo@apple.comce995b22013-12-08 19:01:17 +00001104 break;
oliver@apple.comea771492013-07-25 03:58:38 +00001105 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00001106 DFG_CRASH(m_graph, m_node, "Unrecognized node in FTL backend");
oliver@apple.comea771492013-07-25 03:58:38 +00001107 break;
1108 }
fpizlo@apple.com6a8daef2015-04-22 03:38:17 +00001109
1110 if (m_node->isTerminal())
1111 return false;
1112
1113 if (!m_state.isValid()) {
msaboff@apple.com3fdcb112015-02-01 03:58:39 +00001114 safelyInvalidateAfterTermination();
1115 return false;
1116 }
1117
fpizlo@apple.com9e64b502014-09-16 22:18:23 +00001118 m_availabilityCalculator.executeNode(m_node);
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00001119 m_interpreter.executeEffects(nodeIndex);
oliver@apple.com0d018be2013-07-25 04:00:02 +00001120
1121 return true;
oliver@apple.comea771492013-07-25 03:58:38 +00001122 }
commit-queue@webkit.orga8ee6e62013-10-04 22:45:09 +00001123
oliver@apple.com827d2cf2013-07-25 04:04:45 +00001124 void compileUpsilon()
1125 {
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +00001126 LValue upsilonValue = nullptr;
oliver@apple.com827d2cf2013-07-25 04:04:45 +00001127 switch (m_node->child1().useKind()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001128 case DoubleRepUse:
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +00001129 upsilonValue = lowDouble(m_node->child1());
oliver@apple.com827d2cf2013-07-25 04:04:45 +00001130 break;
1131 case Int32Use:
fpizlo@apple.comf29186e2015-08-26 19:24:41 +00001132 case KnownInt32Use:
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +00001133 upsilonValue = lowInt32(m_node->child1());
oliver@apple.com827d2cf2013-07-25 04:04:45 +00001134 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001135 case Int52RepUse:
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +00001136 upsilonValue = lowInt52(m_node->child1());
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001137 break;
oliver@apple.com827d2cf2013-07-25 04:04:45 +00001138 case BooleanUse:
fpizlo@apple.comf29186e2015-08-26 19:24:41 +00001139 case KnownBooleanUse:
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +00001140 upsilonValue = lowBoolean(m_node->child1());
oliver@apple.com827d2cf2013-07-25 04:04:45 +00001141 break;
1142 case CellUse:
fpizlo@apple.comf29186e2015-08-26 19:24:41 +00001143 case KnownCellUse:
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +00001144 upsilonValue = lowCell(m_node->child1());
oliver@apple.com827d2cf2013-07-25 04:04:45 +00001145 break;
1146 case UntypedUse:
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +00001147 upsilonValue = lowJSValue(m_node->child1());
oliver@apple.com827d2cf2013-07-25 04:04:45 +00001148 break;
1149 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00001150 DFG_CRASH(m_graph, m_node, "Bad use kind");
oliver@apple.com827d2cf2013-07-25 04:04:45 +00001151 break;
1152 }
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +00001153 ValueFromBlock upsilon = m_out.anchor(upsilonValue);
1154 LValue phiNode = m_phis.get(m_node->phi());
benjamin@webkit.org46690602015-11-19 03:09:51 +00001155 m_out.addIncomingToPhi(phiNode, upsilon);
oliver@apple.com827d2cf2013-07-25 04:04:45 +00001156 }
1157
1158 void compilePhi()
1159 {
fpizlo@apple.com9066c532015-11-19 21:25:38 +00001160 LValue phi = m_phis.get(m_node);
1161 m_out.m_block->append(phi);
1162
1163 switch (m_node->flags() & NodeResultMask) {
1164 case NodeResultDouble:
1165 setDouble(phi);
1166 break;
1167 case NodeResultInt32:
1168 setInt32(phi);
1169 break;
1170 case NodeResultInt52:
1171 setInt52(phi);
1172 break;
1173 case NodeResultBoolean:
1174 setBoolean(phi);
1175 break;
1176 case NodeResultJS:
1177 setJSValue(phi);
1178 break;
1179 default:
1180 DFG_CRASH(m_graph, m_node, "Bad use kind");
1181 break;
1182 }
oliver@apple.com827d2cf2013-07-25 04:04:45 +00001183 }
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001184
1185 void compileDoubleConstant()
fpizlo@apple.comf8ec8b42014-03-01 19:57:40 +00001186 {
fpizlo@apple.comb41e6822014-07-25 20:55:17 +00001187 setDouble(m_out.constDouble(m_node->asNumber()));
fpizlo@apple.comf8ec8b42014-03-01 19:57:40 +00001188 }
oliver@apple.com827d2cf2013-07-25 04:04:45 +00001189
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001190 void compileInt52Constant()
1191 {
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00001192 int64_t value = m_node->asAnyInt();
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001193
1194 setInt52(m_out.constInt64(value << JSValue::int52ShiftAmount));
1195 setStrictInt52(m_out.constInt64(value));
1196 }
1197
fpizlo@apple.com024424c2016-03-09 05:16:47 +00001198 void compileLazyJSConstant()
1199 {
1200 PatchpointValue* patchpoint = m_out.patchpoint(Int64);
1201 LazyJSValue value = m_node->lazyJSValue();
1202 patchpoint->setGenerator(
1203 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
1204 value.emit(jit, JSValueRegs(params[0].gpr()));
1205 });
1206 patchpoint->effects = Effects::none();
1207 setJSValue(patchpoint);
1208 }
1209
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001210 void compileDoubleRep()
1211 {
1212 switch (m_node->child1().useKind()) {
fpizlo@apple.com318af072015-06-05 04:59:28 +00001213 case RealNumberUse: {
1214 LValue value = lowJSValue(m_node->child1(), ManualOperandSpeculation);
1215
1216 LValue doubleValue = unboxDouble(value);
1217
fpizlo@apple.com91331742016-03-07 02:07:28 +00001218 LBasicBlock intCase = m_out.newBlock();
1219 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com318af072015-06-05 04:59:28 +00001220
1221 ValueFromBlock fastResult = m_out.anchor(doubleValue);
1222 m_out.branch(
1223 m_out.doubleEqual(doubleValue, doubleValue),
1224 usually(continuation), rarely(intCase));
1225
1226 LBasicBlock lastNext = m_out.appendTo(intCase, continuation);
commit-queue@webkit.orgd8da0f22016-06-04 03:28:57 +00001227
fpizlo@apple.com318af072015-06-05 04:59:28 +00001228 FTL_TYPE_CHECK(
1229 jsValueValue(value), m_node->child1(), SpecBytecodeRealNumber,
commit-queue@webkit.orgd8da0f22016-06-04 03:28:57 +00001230 isNotInt32(value, provenType(m_node->child1()) & ~SpecDoubleReal));
fpizlo@apple.com318af072015-06-05 04:59:28 +00001231 ValueFromBlock slowResult = m_out.anchor(m_out.intToDouble(unboxInt32(value)));
1232 m_out.jump(continuation);
1233
1234 m_out.appendTo(continuation, lastNext);
1235
fpizlo@apple.com994d4532016-07-03 19:34:55 +00001236 setDouble(m_out.phi(Double, fastResult, slowResult));
fpizlo@apple.com318af072015-06-05 04:59:28 +00001237 return;
1238 }
1239
benjamin@webkit.orgbf928092015-05-28 01:30:58 +00001240 case NotCellUse:
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001241 case NumberUse: {
benjamin@webkit.orgbf928092015-05-28 01:30:58 +00001242 bool shouldConvertNonNumber = m_node->child1().useKind() == NotCellUse;
fpizlo@apple.com318af072015-06-05 04:59:28 +00001243
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001244 LValue value = lowJSValue(m_node->child1(), ManualOperandSpeculation);
fpizlo@apple.com318af072015-06-05 04:59:28 +00001245
fpizlo@apple.com91331742016-03-07 02:07:28 +00001246 LBasicBlock intCase = m_out.newBlock();
1247 LBasicBlock doubleTesting = m_out.newBlock();
1248 LBasicBlock doubleCase = m_out.newBlock();
1249 LBasicBlock nonDoubleCase = m_out.newBlock();
1250 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com318af072015-06-05 04:59:28 +00001251
1252 m_out.branch(
1253 isNotInt32(value, provenType(m_node->child1())),
1254 unsure(doubleTesting), unsure(intCase));
1255
1256 LBasicBlock lastNext = m_out.appendTo(intCase, doubleTesting);
1257
1258 ValueFromBlock intToDouble = m_out.anchor(
1259 m_out.intToDouble(unboxInt32(value)));
1260 m_out.jump(continuation);
1261
1262 m_out.appendTo(doubleTesting, doubleCase);
1263 LValue valueIsNumber = isNumber(value, provenType(m_node->child1()));
1264 m_out.branch(valueIsNumber, usually(doubleCase), rarely(nonDoubleCase));
1265
1266 m_out.appendTo(doubleCase, nonDoubleCase);
1267 ValueFromBlock unboxedDouble = m_out.anchor(unboxDouble(value));
1268 m_out.jump(continuation);
1269
1270 if (shouldConvertNonNumber) {
fpizlo@apple.com91331742016-03-07 02:07:28 +00001271 LBasicBlock undefinedCase = m_out.newBlock();
1272 LBasicBlock testNullCase = m_out.newBlock();
1273 LBasicBlock nullCase = m_out.newBlock();
1274 LBasicBlock testBooleanTrueCase = m_out.newBlock();
1275 LBasicBlock convertBooleanTrueCase = m_out.newBlock();
1276 LBasicBlock convertBooleanFalseCase = m_out.newBlock();
fpizlo@apple.com318af072015-06-05 04:59:28 +00001277
1278 m_out.appendTo(nonDoubleCase, undefinedCase);
1279 LValue valueIsUndefined = m_out.equal(value, m_out.constInt64(ValueUndefined));
1280 m_out.branch(valueIsUndefined, unsure(undefinedCase), unsure(testNullCase));
1281
1282 m_out.appendTo(undefinedCase, testNullCase);
1283 ValueFromBlock convertedUndefined = m_out.anchor(m_out.constDouble(PNaN));
1284 m_out.jump(continuation);
1285
1286 m_out.appendTo(testNullCase, nullCase);
1287 LValue valueIsNull = m_out.equal(value, m_out.constInt64(ValueNull));
1288 m_out.branch(valueIsNull, unsure(nullCase), unsure(testBooleanTrueCase));
1289
1290 m_out.appendTo(nullCase, testBooleanTrueCase);
1291 ValueFromBlock convertedNull = m_out.anchor(m_out.constDouble(0));
1292 m_out.jump(continuation);
1293
1294 m_out.appendTo(testBooleanTrueCase, convertBooleanTrueCase);
1295 LValue valueIsBooleanTrue = m_out.equal(value, m_out.constInt64(ValueTrue));
1296 m_out.branch(valueIsBooleanTrue, unsure(convertBooleanTrueCase), unsure(convertBooleanFalseCase));
1297
1298 m_out.appendTo(convertBooleanTrueCase, convertBooleanFalseCase);
1299 ValueFromBlock convertedTrue = m_out.anchor(m_out.constDouble(1));
1300 m_out.jump(continuation);
1301
1302 m_out.appendTo(convertBooleanFalseCase, continuation);
1303
1304 LValue valueIsNotBooleanFalse = m_out.notEqual(value, m_out.constInt64(ValueFalse));
1305 FTL_TYPE_CHECK(jsValueValue(value), m_node->child1(), ~SpecCell, valueIsNotBooleanFalse);
1306 ValueFromBlock convertedFalse = m_out.anchor(m_out.constDouble(0));
1307 m_out.jump(continuation);
1308
1309 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00001310 setDouble(m_out.phi(Double, intToDouble, unboxedDouble, convertedUndefined, convertedNull, convertedTrue, convertedFalse));
fpizlo@apple.com318af072015-06-05 04:59:28 +00001311 return;
1312 }
1313 m_out.appendTo(nonDoubleCase, continuation);
1314 FTL_TYPE_CHECK(jsValueValue(value), m_node->child1(), SpecBytecodeNumber, m_out.booleanTrue);
1315 m_out.unreachable();
1316
1317 m_out.appendTo(continuation, lastNext);
1318
fpizlo@apple.com994d4532016-07-03 19:34:55 +00001319 setDouble(m_out.phi(Double, intToDouble, unboxedDouble));
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001320 return;
1321 }
1322
1323 case Int52RepUse: {
1324 setDouble(strictInt52ToDouble(lowStrictInt52(m_node->child1())));
1325 return;
1326 }
1327
1328 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00001329 DFG_CRASH(m_graph, m_node, "Bad use kind");
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001330 }
1331 }
benjamin@webkit.orgcb584082015-05-08 00:23:32 +00001332
1333 void compileDoubleAsInt32()
1334 {
1335 LValue integerValue = convertDoubleToInt32(lowDouble(m_node->child1()), shouldCheckNegativeZero(m_node->arithMode()));
1336 setInt32(integerValue);
1337 }
1338
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001339 void compileValueRep()
1340 {
1341 switch (m_node->child1().useKind()) {
1342 case DoubleRepUse: {
fpizlo@apple.com85bde1f2014-04-17 04:57:29 +00001343 LValue value = lowDouble(m_node->child1());
1344
1345 if (m_interpreter.needsTypeCheck(m_node->child1(), ~SpecDoubleImpureNaN)) {
1346 value = m_out.select(
1347 m_out.doubleEqual(value, value), value, m_out.constDouble(PNaN));
1348 }
1349
1350 setJSValue(boxDouble(value));
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001351 return;
1352 }
1353
1354 case Int52RepUse: {
1355 setJSValue(strictInt52ToJSValue(lowStrictInt52(m_node->child1())));
1356 return;
1357 }
1358
1359 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00001360 DFG_CRASH(m_graph, m_node, "Bad use kind");
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001361 }
1362 }
1363
1364 void compileInt52Rep()
1365 {
fpizlo@apple.comf2999932014-07-15 00:41:39 +00001366 switch (m_node->child1().useKind()) {
1367 case Int32Use:
commit-queue@webkit.org65fa3e42015-12-04 20:27:37 +00001368 setStrictInt52(m_out.signExt32To64(lowInt32(m_node->child1())));
fpizlo@apple.comf2999932014-07-15 00:41:39 +00001369 return;
1370
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00001371 case AnyIntUse:
fpizlo@apple.comf2999932014-07-15 00:41:39 +00001372 setStrictInt52(
1373 jsValueToStrictInt52(
1374 m_node->child1(), lowJSValue(m_node->child1(), ManualOperandSpeculation)));
1375 return;
1376
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00001377 case DoubleRepAnyIntUse:
fpizlo@apple.comf2999932014-07-15 00:41:39 +00001378 setStrictInt52(
1379 doubleToStrictInt52(
1380 m_node->child1(), lowDouble(m_node->child1())));
1381 return;
1382
1383 default:
1384 RELEASE_ASSERT_NOT_REACHED();
1385 }
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001386 }
1387
1388 void compileValueToInt32()
1389 {
1390 switch (m_node->child1().useKind()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001391 case Int52RepUse:
1392 setInt32(m_out.castToInt32(lowStrictInt52(m_node->child1())));
1393 break;
1394
1395 case DoubleRepUse:
1396 setInt32(doubleToInt32(lowDouble(m_node->child1())));
1397 break;
1398
1399 case NumberUse:
1400 case NotCellUse: {
1401 LoweredNodeValue value = m_int32Values.get(m_node->child1().node());
1402 if (isValid(value)) {
1403 setInt32(value.value());
1404 break;
1405 }
1406
1407 value = m_jsValueValues.get(m_node->child1().node());
1408 if (isValid(value)) {
1409 setInt32(numberOrNotCellToInt32(m_node->child1(), value.value()));
1410 break;
1411 }
1412
1413 // We'll basically just get here for constants. But it's good to have this
1414 // catch-all since we often add new representations into the mix.
1415 setInt32(
1416 numberOrNotCellToInt32(
1417 m_node->child1(),
1418 lowJSValue(m_node->child1(), ManualOperandSpeculation)));
1419 break;
1420 }
1421
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001422 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00001423 DFG_CRASH(m_graph, m_node, "Bad use kind");
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001424 break;
1425 }
1426 }
fpizlo@apple.com96509b72014-05-26 17:43:41 +00001427
1428 void compileBooleanToNumber()
1429 {
1430 switch (m_node->child1().useKind()) {
1431 case BooleanUse: {
fpizlo@apple.com994d4532016-07-03 19:34:55 +00001432 setInt32(m_out.zeroExt(lowBoolean(m_node->child1()), Int32));
fpizlo@apple.com96509b72014-05-26 17:43:41 +00001433 return;
1434 }
1435
1436 case UntypedUse: {
1437 LValue value = lowJSValue(m_node->child1());
1438
fpizlo@apple.comd3389122015-05-19 04:46:26 +00001439 if (!m_interpreter.needsTypeCheck(m_node->child1(), SpecBoolInt32 | SpecBoolean)) {
1440 setInt32(m_out.bitAnd(m_out.castToInt32(value), m_out.int32One));
1441 return;
1442 }
1443
fpizlo@apple.com91331742016-03-07 02:07:28 +00001444 LBasicBlock booleanCase = m_out.newBlock();
1445 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com96509b72014-05-26 17:43:41 +00001446
1447 ValueFromBlock notBooleanResult = m_out.anchor(value);
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00001448 m_out.branch(
1449 isBoolean(value, provenType(m_node->child1())),
1450 unsure(booleanCase), unsure(continuation));
fpizlo@apple.com96509b72014-05-26 17:43:41 +00001451
1452 LBasicBlock lastNext = m_out.appendTo(booleanCase, continuation);
1453 ValueFromBlock booleanResult = m_out.anchor(m_out.bitOr(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00001454 m_out.zeroExt(unboxBoolean(value), Int64), m_tagTypeNumber));
fpizlo@apple.com96509b72014-05-26 17:43:41 +00001455 m_out.jump(continuation);
1456
1457 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00001458 setJSValue(m_out.phi(Int64, booleanResult, notBooleanResult));
fpizlo@apple.com96509b72014-05-26 17:43:41 +00001459 return;
1460 }
1461
1462 default:
1463 RELEASE_ASSERT_NOT_REACHED();
1464 return;
1465 }
1466 }
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001467
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00001468 void compileExtractOSREntryLocal()
1469 {
1470 EncodedJSValue* buffer = static_cast<EncodedJSValue*>(
1471 m_ftlState.jitCode->ftlForOSREntry()->entryBuffer()->dataBuffer());
msaboff@apple.com62aa8b72013-09-26 22:53:54 +00001472 setJSValue(m_out.load64(m_out.absolute(buffer + m_node->unlinkedLocal().toLocal())));
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00001473 }
1474
fpizlo@apple.combcfd8eb2015-02-26 19:51:52 +00001475 void compileGetStack()
oliver@apple.comea771492013-07-25 03:58:38 +00001476 {
fpizlo@apple.com064f0812015-02-16 19:27:37 +00001477 // GetLocals arise only for captured variables and arguments. For arguments, we might have
1478 // already loaded it.
1479 if (LValue value = m_loadedArgumentValues.get(m_node)) {
1480 setJSValue(value);
1481 return;
1482 }
oliver@apple.comea771492013-07-25 03:58:38 +00001483
fpizlo@apple.combcfd8eb2015-02-26 19:51:52 +00001484 StackAccessData* data = m_node->stackAccessData();
1485 AbstractValue& value = m_state.variables().operand(data->local);
1486
1487 DFG_ASSERT(m_graph, m_node, isConcrete(data->format));
1488 DFG_ASSERT(m_graph, m_node, data->format != FlushedDouble); // This just happens to not arise for GetStacks, right now. It would be trivial to support.
oliver@apple.comea771492013-07-25 03:58:38 +00001489
fpizlo@apple.com532f1e52013-09-04 06:26:04 +00001490 if (isInt32Speculation(value.m_type))
fpizlo@apple.combcfd8eb2015-02-26 19:51:52 +00001491 setInt32(m_out.load32(payloadFor(data->machineLocal)));
oliver@apple.com827d2cf2013-07-25 04:04:45 +00001492 else
fpizlo@apple.combcfd8eb2015-02-26 19:51:52 +00001493 setJSValue(m_out.load64(addressFor(data->machineLocal)));
oliver@apple.comea771492013-07-25 03:58:38 +00001494 }
1495
fpizlo@apple.combcfd8eb2015-02-26 19:51:52 +00001496 void compilePutStack()
oliver@apple.comea771492013-07-25 03:58:38 +00001497 {
fpizlo@apple.combcfd8eb2015-02-26 19:51:52 +00001498 StackAccessData* data = m_node->stackAccessData();
1499 switch (data->format) {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001500 case FlushedJSValue: {
fpizlo@apple.com571d3b22013-09-11 21:24:34 +00001501 LValue value = lowJSValue(m_node->child1());
fpizlo@apple.combcfd8eb2015-02-26 19:51:52 +00001502 m_out.store64(value, addressFor(data->machineLocal));
fpizlo@apple.com002405c2013-11-18 01:46:48 +00001503 break;
fpizlo@apple.com571d3b22013-09-11 21:24:34 +00001504 }
oliver@apple.comea771492013-07-25 03:58:38 +00001505
fpizlo@apple.com571d3b22013-09-11 21:24:34 +00001506 case FlushedDouble: {
1507 LValue value = lowDouble(m_node->child1());
fpizlo@apple.combcfd8eb2015-02-26 19:51:52 +00001508 m_out.storeDouble(value, addressFor(data->machineLocal));
fpizlo@apple.com002405c2013-11-18 01:46:48 +00001509 break;
fpizlo@apple.com571d3b22013-09-11 21:24:34 +00001510 }
1511
1512 case FlushedInt32: {
1513 LValue value = lowInt32(m_node->child1());
fpizlo@apple.combcfd8eb2015-02-26 19:51:52 +00001514 m_out.store32(value, payloadFor(data->machineLocal));
fpizlo@apple.com002405c2013-11-18 01:46:48 +00001515 break;
fpizlo@apple.com571d3b22013-09-11 21:24:34 +00001516 }
1517
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001518 case FlushedInt52: {
1519 LValue value = lowInt52(m_node->child1());
fpizlo@apple.combcfd8eb2015-02-26 19:51:52 +00001520 m_out.store64(value, addressFor(data->machineLocal));
fpizlo@apple.com002405c2013-11-18 01:46:48 +00001521 break;
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001522 }
1523
fpizlo@apple.com571d3b22013-09-11 21:24:34 +00001524 case FlushedCell: {
1525 LValue value = lowCell(m_node->child1());
fpizlo@apple.combcfd8eb2015-02-26 19:51:52 +00001526 m_out.store64(value, addressFor(data->machineLocal));
fpizlo@apple.com002405c2013-11-18 01:46:48 +00001527 break;
fpizlo@apple.com571d3b22013-09-11 21:24:34 +00001528 }
1529
1530 case FlushedBoolean: {
1531 speculateBoolean(m_node->child1());
1532 m_out.store64(
1533 lowJSValue(m_node->child1(), ManualOperandSpeculation),
fpizlo@apple.combcfd8eb2015-02-26 19:51:52 +00001534 addressFor(data->machineLocal));
fpizlo@apple.com002405c2013-11-18 01:46:48 +00001535 break;
fpizlo@apple.com571d3b22013-09-11 21:24:34 +00001536 }
1537
fpizlo@apple.com002405c2013-11-18 01:46:48 +00001538 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00001539 DFG_CRASH(m_graph, m_node, "Bad flush format");
fpizlo@apple.com002405c2013-11-18 01:46:48 +00001540 break;
oliver@apple.comea771492013-07-25 03:58:38 +00001541 }
oliver@apple.comea771492013-07-25 03:58:38 +00001542 }
1543
fpizlo@apple.com163291d2015-04-28 19:27:23 +00001544 void compileNoOp()
oliver@apple.comea771492013-07-25 03:58:38 +00001545 {
1546 DFG_NODE_DO_TO_CHILDREN(m_graph, m_node, speculate);
1547 }
keith_miller@apple.comf4a459e2016-05-04 20:15:26 +00001548
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +00001549 void compileCallObjectConstructor()
1550 {
1551 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
1552 LValue value = lowJSValue(m_node->child1());
1553
1554 LBasicBlock isCellCase = m_out.newBlock();
1555 LBasicBlock slowCase = m_out.newBlock();
1556 LBasicBlock continuation = m_out.newBlock();
1557
1558 m_out.branch(isCell(value, provenType(m_node->child1())), usually(isCellCase), rarely(slowCase));
1559
1560 LBasicBlock lastNext = m_out.appendTo(isCellCase, slowCase);
1561 ValueFromBlock fastResult = m_out.anchor(value);
1562 m_out.branch(isObject(value), usually(continuation), rarely(slowCase));
1563
1564 m_out.appendTo(slowCase, continuation);
sbarati@apple.com239d20b2017-01-26 23:50:58 +00001565 ValueFromBlock slowResult = m_out.anchor(vmCall(Int64, m_out.operation(operationObjectConstructor), m_callFrame, weakPointer(globalObject), value));
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +00001566 m_out.jump(continuation);
1567
1568 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00001569 setJSValue(m_out.phi(Int64, fastResult, slowResult));
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +00001570 }
1571
fpizlo@apple.com763818c2014-02-11 02:41:46 +00001572 void compileToThis()
1573 {
1574 LValue value = lowJSValue(m_node->child1());
1575
fpizlo@apple.com91331742016-03-07 02:07:28 +00001576 LBasicBlock isCellCase = m_out.newBlock();
1577 LBasicBlock slowCase = m_out.newBlock();
1578 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com763818c2014-02-11 02:41:46 +00001579
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00001580 m_out.branch(
1581 isCell(value, provenType(m_node->child1())), usually(isCellCase), rarely(slowCase));
fpizlo@apple.com763818c2014-02-11 02:41:46 +00001582
1583 LBasicBlock lastNext = m_out.appendTo(isCellCase, slowCase);
1584 ValueFromBlock fastResult = m_out.anchor(value);
fpizlo@apple.comcbf65c42016-04-18 20:33:47 +00001585 m_out.branch(
1586 m_out.testIsZero32(
1587 m_out.load8ZeroExt32(value, m_heaps.JSCell_typeInfoFlags),
1588 m_out.constInt32(OverridesToThis)),
1589 usually(continuation), rarely(slowCase));
fpizlo@apple.com763818c2014-02-11 02:41:46 +00001590
1591 m_out.appendTo(slowCase, continuation);
1592 J_JITOperation_EJ function;
fpizlo@apple.com6793a322014-02-12 05:42:32 +00001593 if (m_graph.isStrictModeFor(m_node->origin.semantic))
fpizlo@apple.com763818c2014-02-11 02:41:46 +00001594 function = operationToThisStrict;
1595 else
1596 function = operationToThis;
1597 ValueFromBlock slowResult = m_out.anchor(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00001598 vmCall(Int64, m_out.operation(function), m_callFrame, value));
fpizlo@apple.com763818c2014-02-11 02:41:46 +00001599 m_out.jump(continuation);
1600
1601 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00001602 setJSValue(m_out.phi(Int64, fastResult, slowResult));
fpizlo@apple.com763818c2014-02-11 02:41:46 +00001603 }
sbarati@apple.com9a4ad4e2016-07-25 19:04:16 +00001604
fpizlo@apple.com97756552014-01-02 20:15:25 +00001605 void compileValueAdd()
1606 {
benjamin@webkit.org626f77e2016-09-26 21:11:31 +00001607 ArithProfile* arithProfile = m_ftlState.graph.baselineCodeBlockFor(m_node->origin.semantic)->arithProfileForBytecodeOffset(m_node->origin.semantic.bytecodeIndex);
1608 JITAddIC* addIC = codeBlock()->addJITAddIC(arithProfile);
sbarati@apple.com9a4ad4e2016-07-25 19:04:16 +00001609 auto repatchingFunction = operationValueAddOptimize;
1610 auto nonRepatchingFunction = operationValueAdd;
1611 compileMathIC(addIC, repatchingFunction, nonRepatchingFunction);
1612 }
1613
1614 template <typename Generator>
commit-queue@webkit.orgf59f0ed2016-10-15 02:19:16 +00001615 void compileMathIC(JITUnaryMathIC<Generator>* mathIC, FunctionPtr repatchingFunction, FunctionPtr nonRepatchingFunction)
1616 {
1617 Node* node = m_node;
1618
1619 LValue operand = lowJSValue(node->child1());
1620
1621 PatchpointValue* patchpoint = m_out.patchpoint(Int64);
1622 patchpoint->appendSomeRegister(operand);
1623 patchpoint->append(m_tagMask, ValueRep::lateReg(GPRInfo::tagMaskRegister));
1624 patchpoint->append(m_tagTypeNumber, ValueRep::lateReg(GPRInfo::tagTypeNumberRegister));
1625 RefPtr<PatchpointExceptionHandle> exceptionHandle = preparePatchpointForExceptions(patchpoint);
1626 patchpoint->numGPScratchRegisters = 1;
1627 patchpoint->clobber(RegisterSet::macroScratchRegisters());
1628 State* state = &m_ftlState;
1629 patchpoint->setGenerator(
1630 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
1631 AllowMacroScratchRegisterUsage allowScratch(jit);
1632
1633 Box<CCallHelpers::JumpList> exceptions =
1634 exceptionHandle->scheduleExitCreation(params)->jumps(jit);
1635
1636#if ENABLE(MATH_IC_STATS)
1637 auto inlineStart = jit.label();
1638#endif
1639
1640 Box<MathICGenerationState> mathICGenerationState = Box<MathICGenerationState>::create();
1641 mathIC->m_generator = Generator(JSValueRegs(params[0].gpr()), JSValueRegs(params[1].gpr()), params.gpScratch(0));
1642
1643 bool shouldEmitProfiling = false;
1644 bool generatedInline = mathIC->generateInline(jit, *mathICGenerationState, shouldEmitProfiling);
1645
1646 if (generatedInline) {
1647 ASSERT(!mathICGenerationState->slowPathJumps.empty());
1648 auto done = jit.label();
1649 params.addLatePath([=] (CCallHelpers& jit) {
1650 AllowMacroScratchRegisterUsage allowScratch(jit);
1651 mathICGenerationState->slowPathJumps.link(&jit);
1652 mathICGenerationState->slowPathStart = jit.label();
1653#if ENABLE(MATH_IC_STATS)
1654 auto slowPathStart = jit.label();
1655#endif
1656
1657 if (mathICGenerationState->shouldSlowPathRepatch) {
1658 SlowPathCall call = callOperation(*state, params.unavailableRegisters(), jit, node->origin.semantic, exceptions.get(),
1659 repatchingFunction, params[0].gpr(), params[1].gpr(), CCallHelpers::TrustedImmPtr(mathIC));
1660 mathICGenerationState->slowPathCall = call.call();
1661 } else {
1662 SlowPathCall call = callOperation(*state, params.unavailableRegisters(), jit, node->origin.semantic,
1663 exceptions.get(), nonRepatchingFunction, params[0].gpr(), params[1].gpr());
1664 mathICGenerationState->slowPathCall = call.call();
1665 }
1666 jit.jump().linkTo(done, &jit);
1667
1668 jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
1669 mathIC->finalizeInlineCode(*mathICGenerationState, linkBuffer);
1670 });
1671
1672#if ENABLE(MATH_IC_STATS)
1673 auto slowPathEnd = jit.label();
1674 jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
1675 size_t size = static_cast<char*>(linkBuffer.locationOf(slowPathEnd).executableAddress()) - static_cast<char*>(linkBuffer.locationOf(slowPathStart).executableAddress());
1676 mathIC->m_generatedCodeSize += size;
1677 });
1678#endif
1679 });
1680 } else {
1681 callOperation(
1682 *state, params.unavailableRegisters(), jit, node->origin.semantic, exceptions.get(),
1683 nonRepatchingFunction, params[0].gpr(), params[1].gpr());
1684 }
1685
1686#if ENABLE(MATH_IC_STATS)
1687 auto inlineEnd = jit.label();
1688 jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
1689 size_t size = static_cast<char*>(linkBuffer.locationOf(inlineEnd).executableAddress()) - static_cast<char*>(linkBuffer.locationOf(inlineStart).executableAddress());
1690 mathIC->m_generatedCodeSize += size;
1691 });
1692#endif
1693 });
1694
1695 setJSValue(patchpoint);
1696 }
1697
1698 template <typename Generator>
commit-queue@webkit.org4c2202a2016-09-23 03:50:22 +00001699 void compileMathIC(JITBinaryMathIC<Generator>* mathIC, FunctionPtr repatchingFunction, FunctionPtr nonRepatchingFunction)
sbarati@apple.com9a4ad4e2016-07-25 19:04:16 +00001700 {
sbarati@apple.comb0b1eb52016-07-21 23:41:44 +00001701 Node* node = m_node;
1702
1703 LValue left = lowJSValue(node->child1());
1704 LValue right = lowJSValue(node->child2());
1705
1706 SnippetOperand leftOperand(m_state.forNode(node->child1()).resultType());
1707 SnippetOperand rightOperand(m_state.forNode(node->child2()).resultType());
1708
1709 PatchpointValue* patchpoint = m_out.patchpoint(Int64);
1710 patchpoint->appendSomeRegister(left);
1711 patchpoint->appendSomeRegister(right);
1712 patchpoint->append(m_tagMask, ValueRep::lateReg(GPRInfo::tagMaskRegister));
1713 patchpoint->append(m_tagTypeNumber, ValueRep::lateReg(GPRInfo::tagTypeNumberRegister));
1714 RefPtr<PatchpointExceptionHandle> exceptionHandle =
1715 preparePatchpointForExceptions(patchpoint);
1716 patchpoint->numGPScratchRegisters = 1;
1717 patchpoint->numFPScratchRegisters = 2;
1718 patchpoint->clobber(RegisterSet::macroScratchRegisters());
1719 State* state = &m_ftlState;
1720 patchpoint->setGenerator(
1721 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
1722 AllowMacroScratchRegisterUsage allowScratch(jit);
1723
1724 Box<CCallHelpers::JumpList> exceptions =
1725 exceptionHandle->scheduleExitCreation(params)->jumps(jit);
1726
sbarati@apple.comff204392016-07-25 20:40:39 +00001727#if ENABLE(MATH_IC_STATS)
1728 auto inlineStart = jit.label();
1729#endif
1730
sbarati@apple.com9a4ad4e2016-07-25 19:04:16 +00001731 Box<MathICGenerationState> mathICGenerationState = Box<MathICGenerationState>::create();
sbarati@apple.com9a4ad4e2016-07-25 19:04:16 +00001732 mathIC->m_generator = Generator(leftOperand, rightOperand, JSValueRegs(params[0].gpr()),
sbarati@apple.comb0b1eb52016-07-21 23:41:44 +00001733 JSValueRegs(params[1].gpr()), JSValueRegs(params[2].gpr()), params.fpScratch(0),
benjamin@webkit.org626f77e2016-09-26 21:11:31 +00001734 params.fpScratch(1), params.gpScratch(0), InvalidFPRReg);
sbarati@apple.comb0b1eb52016-07-21 23:41:44 +00001735
sbarati@apple.com9a4ad4e2016-07-25 19:04:16 +00001736 bool shouldEmitProfiling = false;
1737 bool generatedInline = mathIC->generateInline(jit, *mathICGenerationState, shouldEmitProfiling);
sbarati@apple.comb0b1eb52016-07-21 23:41:44 +00001738
1739 if (generatedInline) {
sbarati@apple.com9a4ad4e2016-07-25 19:04:16 +00001740 ASSERT(!mathICGenerationState->slowPathJumps.empty());
sbarati@apple.comb0b1eb52016-07-21 23:41:44 +00001741 auto done = jit.label();
1742 params.addLatePath([=] (CCallHelpers& jit) {
1743 AllowMacroScratchRegisterUsage allowScratch(jit);
sbarati@apple.com9a4ad4e2016-07-25 19:04:16 +00001744 mathICGenerationState->slowPathJumps.link(&jit);
1745 mathICGenerationState->slowPathStart = jit.label();
sbarati@apple.comff204392016-07-25 20:40:39 +00001746#if ENABLE(MATH_IC_STATS)
1747 auto slowPathStart = jit.label();
1748#endif
sbarati@apple.comb0b1eb52016-07-21 23:41:44 +00001749
sbarati@apple.com9a4ad4e2016-07-25 19:04:16 +00001750 if (mathICGenerationState->shouldSlowPathRepatch) {
sbarati@apple.comb0b1eb52016-07-21 23:41:44 +00001751 SlowPathCall call = callOperation(*state, params.unavailableRegisters(), jit, node->origin.semantic, exceptions.get(),
sbarati@apple.com9a4ad4e2016-07-25 19:04:16 +00001752 repatchingFunction, params[0].gpr(), params[1].gpr(), params[2].gpr(), CCallHelpers::TrustedImmPtr(mathIC));
1753 mathICGenerationState->slowPathCall = call.call();
sbarati@apple.comb0b1eb52016-07-21 23:41:44 +00001754 } else {
1755 SlowPathCall call = callOperation(*state, params.unavailableRegisters(), jit, node->origin.semantic,
sbarati@apple.com9a4ad4e2016-07-25 19:04:16 +00001756 exceptions.get(), nonRepatchingFunction, params[0].gpr(), params[1].gpr(), params[2].gpr());
1757 mathICGenerationState->slowPathCall = call.call();
sbarati@apple.comb0b1eb52016-07-21 23:41:44 +00001758 }
1759 jit.jump().linkTo(done, &jit);
1760
1761 jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
sbarati@apple.com9a4ad4e2016-07-25 19:04:16 +00001762 mathIC->finalizeInlineCode(*mathICGenerationState, linkBuffer);
sbarati@apple.comb0b1eb52016-07-21 23:41:44 +00001763 });
sbarati@apple.comff204392016-07-25 20:40:39 +00001764
1765#if ENABLE(MATH_IC_STATS)
1766 auto slowPathEnd = jit.label();
1767 jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
1768 size_t size = static_cast<char*>(linkBuffer.locationOf(slowPathEnd).executableAddress()) - static_cast<char*>(linkBuffer.locationOf(slowPathStart).executableAddress());
1769 mathIC->m_generatedCodeSize += size;
1770 });
1771#endif
sbarati@apple.comb0b1eb52016-07-21 23:41:44 +00001772 });
1773 } else {
1774 callOperation(
1775 *state, params.unavailableRegisters(), jit, node->origin.semantic, exceptions.get(),
sbarati@apple.com9a4ad4e2016-07-25 19:04:16 +00001776 nonRepatchingFunction, params[0].gpr(), params[1].gpr(), params[2].gpr());
sbarati@apple.comb0b1eb52016-07-21 23:41:44 +00001777 }
sbarati@apple.comff204392016-07-25 20:40:39 +00001778
1779#if ENABLE(MATH_IC_STATS)
1780 auto inlineEnd = jit.label();
1781 jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
1782 size_t size = static_cast<char*>(linkBuffer.locationOf(inlineEnd).executableAddress()) - static_cast<char*>(linkBuffer.locationOf(inlineStart).executableAddress());
1783 mathIC->m_generatedCodeSize += size;
1784 });
1785#endif
sbarati@apple.comb0b1eb52016-07-21 23:41:44 +00001786 });
1787
1788 setJSValue(patchpoint);
fpizlo@apple.com97756552014-01-02 20:15:25 +00001789 }
1790
fpizlo@apple.comb3b187c2015-08-22 18:35:47 +00001791 void compileStrCat()
1792 {
1793 LValue result;
1794 if (m_node->child3()) {
1795 result = vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00001796 Int64, m_out.operation(operationStrCat3), m_callFrame,
fpizlo@apple.com2b150e782015-08-27 23:59:57 +00001797 lowJSValue(m_node->child1(), ManualOperandSpeculation),
1798 lowJSValue(m_node->child2(), ManualOperandSpeculation),
1799 lowJSValue(m_node->child3(), ManualOperandSpeculation));
fpizlo@apple.comb3b187c2015-08-22 18:35:47 +00001800 } else {
1801 result = vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00001802 Int64, m_out.operation(operationStrCat2), m_callFrame,
fpizlo@apple.com2b150e782015-08-27 23:59:57 +00001803 lowJSValue(m_node->child1(), ManualOperandSpeculation),
1804 lowJSValue(m_node->child2(), ManualOperandSpeculation));
fpizlo@apple.comb3b187c2015-08-22 18:35:47 +00001805 }
1806 setJSValue(result);
1807 }
1808
msaboff@apple.com95894332014-01-29 19:18:54 +00001809 void compileArithAddOrSub()
oliver@apple.comea771492013-07-25 03:58:38 +00001810 {
commit-queue@webkit.orgcf827eb2013-10-02 18:52:19 +00001811 bool isSub = m_node->op() == ArithSub;
oliver@apple.comea771492013-07-25 03:58:38 +00001812 switch (m_node->binaryUseKind()) {
1813 case Int32Use: {
1814 LValue left = lowInt32(m_node->child1());
1815 LValue right = lowInt32(m_node->child2());
commit-queue@webkit.org0e3c2682013-10-01 23:18:47 +00001816
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +00001817 if (!shouldCheckOverflow(m_node->arithMode())) {
msaboff@apple.com95894332014-01-29 19:18:54 +00001818 setInt32(isSub ? m_out.sub(left, right) : m_out.add(left, right));
oliver@apple.comea771492013-07-25 03:58:38 +00001819 break;
1820 }
commit-queue@webkit.orga97a9512013-09-30 06:32:59 +00001821
fpizlo@apple.com45e45652016-01-07 21:20:37 +00001822 CheckValue* result =
fpizlo@apple.combce60f82015-11-19 20:03:22 +00001823 isSub ? m_out.speculateSub(left, right) : m_out.speculateAdd(left, right);
1824 blessSpeculation(result, Overflow, noValue(), nullptr, m_origin);
1825 setInt32(result);
oliver@apple.comea771492013-07-25 03:58:38 +00001826 break;
1827 }
1828
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001829 case Int52RepUse: {
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00001830 if (!abstractValue(m_node->child1()).couldBeType(SpecInt52Only)
1831 && !abstractValue(m_node->child2()).couldBeType(SpecInt52Only)) {
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001832 Int52Kind kind;
1833 LValue left = lowWhicheverInt52(m_node->child1(), kind);
1834 LValue right = lowInt52(m_node->child2(), kind);
commit-queue@webkit.orga97a9512013-09-30 06:32:59 +00001835 setInt52(isSub ? m_out.sub(left, right) : m_out.add(left, right), kind);
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001836 break;
1837 }
fpizlo@apple.combce60f82015-11-19 20:03:22 +00001838
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001839 LValue left = lowInt52(m_node->child1());
1840 LValue right = lowInt52(m_node->child2());
fpizlo@apple.com45e45652016-01-07 21:20:37 +00001841 CheckValue* result =
fpizlo@apple.combce60f82015-11-19 20:03:22 +00001842 isSub ? m_out.speculateSub(left, right) : m_out.speculateAdd(left, right);
1843 blessSpeculation(result, Overflow, noValue(), nullptr, m_origin);
1844 setInt52(result);
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001845 break;
1846 }
1847
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001848 case DoubleRepUse: {
commit-queue@webkit.orga97a9512013-09-30 06:32:59 +00001849 LValue C1 = lowDouble(m_node->child1());
1850 LValue C2 = lowDouble(m_node->child2());
1851
1852 setDouble(isSub ? m_out.doubleSub(C1, C2) : m_out.doubleAdd(C1, C2));
oliver@apple.com32295c12013-07-25 03:59:06 +00001853 break;
1854 }
mark.lam@apple.com2d70d992015-10-28 18:36:02 +00001855
1856 case UntypedUse: {
1857 if (!isSub) {
1858 DFG_CRASH(m_graph, m_node, "Bad use kind");
1859 break;
1860 }
fpizlo@apple.comb19cd822016-01-04 20:49:33 +00001861
benjamin@webkit.org626f77e2016-09-26 21:11:31 +00001862 ArithProfile* arithProfile = m_ftlState.graph.baselineCodeBlockFor(m_node->origin.semantic)->arithProfileForBytecodeOffset(m_node->origin.semantic.bytecodeIndex);
1863 JITSubIC* subIC = codeBlock()->addJITSubIC(arithProfile);
sbarati@apple.com3e7ec7d2016-08-01 18:48:14 +00001864 auto repatchingFunction = operationValueSubOptimize;
1865 auto nonRepatchingFunction = operationValueSub;
1866 compileMathIC(subIC, repatchingFunction, nonRepatchingFunction);
mark.lam@apple.com2d70d992015-10-28 18:36:02 +00001867 break;
1868 }
1869
oliver@apple.comea771492013-07-25 03:58:38 +00001870 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00001871 DFG_CRASH(m_graph, m_node, "Bad use kind");
oliver@apple.comea771492013-07-25 03:58:38 +00001872 break;
1873 }
1874 }
benjamin@webkit.orge324d432015-04-26 19:55:18 +00001875
1876 void compileArithClz32()
1877 {
commit-queue@webkit.org95f28be2016-09-06 21:54:11 +00001878 if (m_node->child1().useKind() == Int32Use || m_node->child1().useKind() == KnownInt32Use) {
1879 LValue operand = lowInt32(m_node->child1());
1880 setInt32(m_out.ctlz32(operand));
1881 return;
1882 }
1883 DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == UntypedUse);
1884 LValue argument = lowJSValue(m_node->child1());
1885 LValue result = vmCall(Int32, m_out.operation(operationArithClz32), m_callFrame, argument);
1886 setInt32(result);
benjamin@webkit.orge324d432015-04-26 19:55:18 +00001887 }
oliver@apple.comea771492013-07-25 03:58:38 +00001888
1889 void compileArithMul()
1890 {
1891 switch (m_node->binaryUseKind()) {
1892 case Int32Use: {
1893 LValue left = lowInt32(m_node->child1());
1894 LValue right = lowInt32(m_node->child2());
msaboff@apple.com95894332014-01-29 19:18:54 +00001895
1896 LValue result;
commit-queue@webkit.org0e3c2682013-10-01 23:18:47 +00001897
msaboff@apple.com95894332014-01-29 19:18:54 +00001898 if (!shouldCheckOverflow(m_node->arithMode()))
1899 result = m_out.mul(left, right);
1900 else {
fpizlo@apple.com45e45652016-01-07 21:20:37 +00001901 CheckValue* speculation = m_out.speculateMul(left, right);
fpizlo@apple.combce60f82015-11-19 20:03:22 +00001902 blessSpeculation(speculation, Overflow, noValue(), nullptr, m_origin);
1903 result = speculation;
oliver@apple.comea771492013-07-25 03:58:38 +00001904 }
1905
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +00001906 if (shouldCheckNegativeZero(m_node->arithMode())) {
fpizlo@apple.com91331742016-03-07 02:07:28 +00001907 LBasicBlock slowCase = m_out.newBlock();
1908 LBasicBlock continuation = m_out.newBlock();
oliver@apple.comea771492013-07-25 03:58:38 +00001909
fpizlo@apple.com975ae502014-02-19 22:29:43 +00001910 m_out.branch(
1911 m_out.notZero32(result), usually(continuation), rarely(slowCase));
oliver@apple.comdd372b72013-07-25 04:01:08 +00001912
oliver@apple.comea771492013-07-25 03:58:38 +00001913 LBasicBlock lastNext = m_out.appendTo(slowCase, continuation);
fpizlo@apple.comc6ca1042016-01-19 19:20:35 +00001914 speculate(NegativeZero, noValue(), nullptr, m_out.lessThan(left, m_out.int32Zero));
1915 speculate(NegativeZero, noValue(), nullptr, m_out.lessThan(right, m_out.int32Zero));
oliver@apple.comea771492013-07-25 03:58:38 +00001916 m_out.jump(continuation);
1917 m_out.appendTo(continuation, lastNext);
1918 }
1919
oliver@apple.com827d2cf2013-07-25 04:04:45 +00001920 setInt32(result);
oliver@apple.comea771492013-07-25 03:58:38 +00001921 break;
1922 }
1923
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001924 case Int52RepUse: {
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001925 Int52Kind kind;
1926 LValue left = lowWhicheverInt52(m_node->child1(), kind);
1927 LValue right = lowInt52(m_node->child2(), opposite(kind));
commit-queue@webkit.org0e3c2682013-10-01 23:18:47 +00001928
fpizlo@apple.com45e45652016-01-07 21:20:37 +00001929 CheckValue* result = m_out.speculateMul(left, right);
fpizlo@apple.combce60f82015-11-19 20:03:22 +00001930 blessSpeculation(result, Overflow, noValue(), nullptr, m_origin);
commit-queue@webkit.org0e3c2682013-10-01 23:18:47 +00001931
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +00001932 if (shouldCheckNegativeZero(m_node->arithMode())) {
fpizlo@apple.com91331742016-03-07 02:07:28 +00001933 LBasicBlock slowCase = m_out.newBlock();
1934 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001935
fpizlo@apple.com975ae502014-02-19 22:29:43 +00001936 m_out.branch(
1937 m_out.notZero64(result), usually(continuation), rarely(slowCase));
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001938
1939 LBasicBlock lastNext = m_out.appendTo(slowCase, continuation);
fpizlo@apple.comc6ca1042016-01-19 19:20:35 +00001940 speculate(NegativeZero, noValue(), nullptr, m_out.lessThan(left, m_out.int64Zero));
1941 speculate(NegativeZero, noValue(), nullptr, m_out.lessThan(right, m_out.int64Zero));
fpizlo@apple.com6921b292013-09-18 17:14:02 +00001942 m_out.jump(continuation);
1943 m_out.appendTo(continuation, lastNext);
1944 }
1945
1946 setInt52(result);
1947 break;
1948 }
1949
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00001950 case DoubleRepUse: {
oliver@apple.com827d2cf2013-07-25 04:04:45 +00001951 setDouble(
oliver@apple.com32295c12013-07-25 03:59:06 +00001952 m_out.doubleMul(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
1953 break;
1954 }
mark.lam@apple.com1d936142015-12-03 05:42:56 +00001955
1956 case UntypedUse: {
benjamin@webkit.org626f77e2016-09-26 21:11:31 +00001957 ArithProfile* arithProfile = m_ftlState.graph.baselineCodeBlockFor(m_node->origin.semantic)->arithProfileForBytecodeOffset(m_node->origin.semantic.bytecodeIndex);
1958 JITMulIC* mulIC = codeBlock()->addJITMulIC(arithProfile);
sbarati@apple.com9a4ad4e2016-07-25 19:04:16 +00001959 auto repatchingFunction = operationValueMulOptimize;
1960 auto nonRepatchingFunction = operationValueMul;
1961 compileMathIC(mulIC, repatchingFunction, nonRepatchingFunction);
mark.lam@apple.com1d936142015-12-03 05:42:56 +00001962 break;
1963 }
1964
oliver@apple.comea771492013-07-25 03:58:38 +00001965 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00001966 DFG_CRASH(m_graph, m_node, "Bad use kind");
oliver@apple.comea771492013-07-25 03:58:38 +00001967 break;
1968 }
1969 }
commit-queue@webkit.orgcf827eb2013-10-02 18:52:19 +00001970
msaboff@apple.com95894332014-01-29 19:18:54 +00001971 void compileArithDiv()
oliver@apple.comdd372b72013-07-25 04:01:08 +00001972 {
1973 switch (m_node->binaryUseKind()) {
1974 case Int32Use: {
1975 LValue numerator = lowInt32(m_node->child1());
1976 LValue denominator = lowInt32(m_node->child2());
commit-queue@webkit.org3e0d7422015-12-04 20:32:21 +00001977
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +00001978 if (shouldCheckNegativeZero(m_node->arithMode())) {
fpizlo@apple.com91331742016-03-07 02:07:28 +00001979 LBasicBlock zeroNumerator = m_out.newBlock();
1980 LBasicBlock numeratorContinuation = m_out.newBlock();
commit-queue@webkit.org3e0d7422015-12-04 20:32:21 +00001981
fpizlo@apple.com975ae502014-02-19 22:29:43 +00001982 m_out.branch(
1983 m_out.isZero32(numerator),
1984 rarely(zeroNumerator), usually(numeratorContinuation));
commit-queue@webkit.org3e0d7422015-12-04 20:32:21 +00001985
oliver@apple.comdd372b72013-07-25 04:01:08 +00001986 LBasicBlock innerLastNext = m_out.appendTo(zeroNumerator, numeratorContinuation);
commit-queue@webkit.org3e0d7422015-12-04 20:32:21 +00001987
oliver@apple.comdd372b72013-07-25 04:01:08 +00001988 speculate(
1989 NegativeZero, noValue(), 0, m_out.lessThan(denominator, m_out.int32Zero));
commit-queue@webkit.org3e0d7422015-12-04 20:32:21 +00001990
oliver@apple.comdd372b72013-07-25 04:01:08 +00001991 m_out.jump(numeratorContinuation);
commit-queue@webkit.org3e0d7422015-12-04 20:32:21 +00001992
oliver@apple.comdd372b72013-07-25 04:01:08 +00001993 m_out.appendTo(numeratorContinuation, innerLastNext);
1994 }
1995
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +00001996 if (shouldCheckOverflow(m_node->arithMode())) {
fpizlo@apple.com91331742016-03-07 02:07:28 +00001997 LBasicBlock unsafeDenominator = m_out.newBlock();
1998 LBasicBlock continuation = m_out.newBlock();
commit-queue@webkit.org3e0d7422015-12-04 20:32:21 +00001999
2000 LValue adjustedDenominator = m_out.add(denominator, m_out.int32One);
2001 m_out.branch(
2002 m_out.above(adjustedDenominator, m_out.int32One),
2003 usually(continuation), rarely(unsafeDenominator));
2004
2005 LBasicBlock lastNext = m_out.appendTo(unsafeDenominator, continuation);
2006 LValue neg2ToThe31 = m_out.constInt32(-2147483647-1);
fpizlo@apple.comc6ca1042016-01-19 19:20:35 +00002007 speculate(Overflow, noValue(), nullptr, m_out.isZero32(denominator));
2008 speculate(Overflow, noValue(), nullptr, m_out.equal(numerator, neg2ToThe31));
commit-queue@webkit.org3e0d7422015-12-04 20:32:21 +00002009 m_out.jump(continuation);
2010
2011 m_out.appendTo(continuation, lastNext);
2012 LValue result = m_out.div(numerator, denominator);
oliver@apple.comdd372b72013-07-25 04:01:08 +00002013 speculate(
2014 Overflow, noValue(), 0,
msaboff@apple.com95894332014-01-29 19:18:54 +00002015 m_out.notEqual(m_out.mul(result, denominator), numerator));
commit-queue@webkit.org3e0d7422015-12-04 20:32:21 +00002016 setInt32(result);
2017 } else
2018 setInt32(m_out.chillDiv(numerator, denominator));
2019
oliver@apple.comdd372b72013-07-25 04:01:08 +00002020 break;
2021 }
2022
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00002023 case DoubleRepUse: {
msaboff@apple.com95894332014-01-29 19:18:54 +00002024 setDouble(m_out.doubleDiv(
2025 lowDouble(m_node->child1()), lowDouble(m_node->child2())));
oliver@apple.comdd372b72013-07-25 04:01:08 +00002026 break;
2027 }
mark.lam@apple.com224ce4d2015-12-08 21:44:12 +00002028
2029 case UntypedUse: {
fpizlo@apple.come41ca562016-01-04 21:33:37 +00002030 emitBinarySnippet<JITDivGenerator, NeedScratchFPR>(operationValueDiv);
mark.lam@apple.com224ce4d2015-12-08 21:44:12 +00002031 break;
2032 }
2033
oliver@apple.comdd372b72013-07-25 04:01:08 +00002034 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00002035 DFG_CRASH(m_graph, m_node, "Bad use kind");
oliver@apple.comdd372b72013-07-25 04:01:08 +00002036 break;
2037 }
2038 }
2039
msaboff@apple.com95894332014-01-29 19:18:54 +00002040 void compileArithMod()
2041 {
2042 switch (m_node->binaryUseKind()) {
2043 case Int32Use: {
2044 LValue numerator = lowInt32(m_node->child1());
2045 LValue denominator = lowInt32(m_node->child2());
commit-queue@webkit.org0dfe4aa2015-12-11 00:31:51 +00002046
2047 LValue remainder;
msaboff@apple.com95894332014-01-29 19:18:54 +00002048 if (shouldCheckOverflow(m_node->arithMode())) {
fpizlo@apple.com91331742016-03-07 02:07:28 +00002049 LBasicBlock unsafeDenominator = m_out.newBlock();
2050 LBasicBlock continuation = m_out.newBlock();
commit-queue@webkit.org0dfe4aa2015-12-11 00:31:51 +00002051
2052 LValue adjustedDenominator = m_out.add(denominator, m_out.int32One);
2053 m_out.branch(
2054 m_out.above(adjustedDenominator, m_out.int32One),
2055 usually(continuation), rarely(unsafeDenominator));
2056
2057 LBasicBlock lastNext = m_out.appendTo(unsafeDenominator, continuation);
2058 LValue neg2ToThe31 = m_out.constInt32(-2147483647-1);
fpizlo@apple.comc6ca1042016-01-19 19:20:35 +00002059 speculate(Overflow, noValue(), nullptr, m_out.isZero32(denominator));
2060 speculate(Overflow, noValue(), nullptr, m_out.equal(numerator, neg2ToThe31));
msaboff@apple.com95894332014-01-29 19:18:54 +00002061 m_out.jump(continuation);
commit-queue@webkit.org0dfe4aa2015-12-11 00:31:51 +00002062
2063 m_out.appendTo(continuation, lastNext);
2064 LValue result = m_out.mod(numerator, denominator);
2065 remainder = result;
2066 } else
2067 remainder = m_out.chillMod(numerator, denominator);
2068
msaboff@apple.com95894332014-01-29 19:18:54 +00002069 if (shouldCheckNegativeZero(m_node->arithMode())) {
fpizlo@apple.com91331742016-03-07 02:07:28 +00002070 LBasicBlock negativeNumerator = m_out.newBlock();
2071 LBasicBlock numeratorContinuation = m_out.newBlock();
commit-queue@webkit.org0dfe4aa2015-12-11 00:31:51 +00002072
msaboff@apple.com95894332014-01-29 19:18:54 +00002073 m_out.branch(
2074 m_out.lessThan(numerator, m_out.int32Zero),
fpizlo@apple.com975ae502014-02-19 22:29:43 +00002075 unsure(negativeNumerator), unsure(numeratorContinuation));
commit-queue@webkit.org0dfe4aa2015-12-11 00:31:51 +00002076
msaboff@apple.com95894332014-01-29 19:18:54 +00002077 LBasicBlock innerLastNext = m_out.appendTo(negativeNumerator, numeratorContinuation);
commit-queue@webkit.org0dfe4aa2015-12-11 00:31:51 +00002078
msaboff@apple.com95894332014-01-29 19:18:54 +00002079 speculate(NegativeZero, noValue(), 0, m_out.isZero32(remainder));
commit-queue@webkit.org0dfe4aa2015-12-11 00:31:51 +00002080
msaboff@apple.com95894332014-01-29 19:18:54 +00002081 m_out.jump(numeratorContinuation);
commit-queue@webkit.org0dfe4aa2015-12-11 00:31:51 +00002082
msaboff@apple.com95894332014-01-29 19:18:54 +00002083 m_out.appendTo(numeratorContinuation, innerLastNext);
2084 }
commit-queue@webkit.org0dfe4aa2015-12-11 00:31:51 +00002085
2086 setInt32(remainder);
msaboff@apple.com95894332014-01-29 19:18:54 +00002087 break;
2088 }
2089
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00002090 case DoubleRepUse: {
msaboff@apple.com95894332014-01-29 19:18:54 +00002091 setDouble(
commit-queue@webkit.org0dfe4aa2015-12-11 00:31:51 +00002092 m_out.doubleMod(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
msaboff@apple.com95894332014-01-29 19:18:54 +00002093 break;
2094 }
2095
2096 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00002097 DFG_CRASH(m_graph, m_node, "Bad use kind");
msaboff@apple.com95894332014-01-29 19:18:54 +00002098 break;
2099 }
2100 }
2101
oliver@apple.com61cccb82013-07-25 04:01:30 +00002102 void compileArithMinOrMax()
2103 {
2104 switch (m_node->binaryUseKind()) {
2105 case Int32Use: {
2106 LValue left = lowInt32(m_node->child1());
2107 LValue right = lowInt32(m_node->child2());
2108
oliver@apple.com827d2cf2013-07-25 04:04:45 +00002109 setInt32(
oliver@apple.com61cccb82013-07-25 04:01:30 +00002110 m_out.select(
2111 m_node->op() == ArithMin
2112 ? m_out.lessThan(left, right)
2113 : m_out.lessThan(right, left),
2114 left, right));
2115 break;
2116 }
2117
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00002118 case DoubleRepUse: {
oliver@apple.com61cccb82013-07-25 04:01:30 +00002119 LValue left = lowDouble(m_node->child1());
2120 LValue right = lowDouble(m_node->child2());
2121
fpizlo@apple.com91331742016-03-07 02:07:28 +00002122 LBasicBlock notLessThan = m_out.newBlock();
2123 LBasicBlock continuation = m_out.newBlock();
oliver@apple.com61cccb82013-07-25 04:01:30 +00002124
2125 Vector<ValueFromBlock, 2> results;
2126
2127 results.append(m_out.anchor(left));
2128 m_out.branch(
2129 m_node->op() == ArithMin
2130 ? m_out.doubleLessThan(left, right)
2131 : m_out.doubleGreaterThan(left, right),
fpizlo@apple.com975ae502014-02-19 22:29:43 +00002132 unsure(continuation), unsure(notLessThan));
oliver@apple.com61cccb82013-07-25 04:01:30 +00002133
2134 LBasicBlock lastNext = m_out.appendTo(notLessThan, continuation);
2135 results.append(m_out.anchor(m_out.select(
2136 m_node->op() == ArithMin
2137 ? m_out.doubleGreaterThanOrEqual(left, right)
2138 : m_out.doubleLessThanOrEqual(left, right),
achristensen@apple.comd867de72014-06-18 23:42:57 +00002139 right, m_out.constDouble(PNaN))));
oliver@apple.com61cccb82013-07-25 04:01:30 +00002140 m_out.jump(continuation);
2141
2142 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00002143 setDouble(m_out.phi(Double, results));
oliver@apple.com61cccb82013-07-25 04:01:30 +00002144 break;
2145 }
2146
2147 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00002148 DFG_CRASH(m_graph, m_node, "Bad use kind");
oliver@apple.com61cccb82013-07-25 04:01:30 +00002149 break;
2150 }
2151 }
oliver@apple.comd533b1832013-07-25 04:01:22 +00002152
oliver@apple.com0452e562013-07-25 04:01:40 +00002153 void compileArithAbs()
2154 {
2155 switch (m_node->child1().useKind()) {
2156 case Int32Use: {
2157 LValue value = lowInt32(m_node->child1());
commit-queue@webkit.orgf4256ed2016-02-17 23:35:11 +00002158
oliver@apple.com0452e562013-07-25 04:01:40 +00002159 LValue mask = m_out.aShr(value, m_out.constInt32(31));
2160 LValue result = m_out.bitXor(mask, m_out.add(mask, value));
commit-queue@webkit.orgf4256ed2016-02-17 23:35:11 +00002161
2162 if (shouldCheckOverflow(m_node->arithMode()))
benjamin@webkit.org1d49b272016-03-07 18:30:31 +00002163 speculate(Overflow, noValue(), 0, m_out.lessThan(result, m_out.int32Zero));
commit-queue@webkit.orgf4256ed2016-02-17 23:35:11 +00002164
oliver@apple.com827d2cf2013-07-25 04:04:45 +00002165 setInt32(result);
oliver@apple.com0452e562013-07-25 04:01:40 +00002166 break;
2167 }
2168
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00002169 case DoubleRepUse: {
oliver@apple.com827d2cf2013-07-25 04:04:45 +00002170 setDouble(m_out.doubleAbs(lowDouble(m_node->child1())));
oliver@apple.com0452e562013-07-25 04:01:40 +00002171 break;
2172 }
2173
commit-queue@webkit.org0ec71072016-08-29 07:21:04 +00002174 default: {
2175 DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == UntypedUse);
2176 LValue argument = lowJSValue(m_node->child1());
2177 LValue result = vmCall(Double, m_out.operation(operationArithAbs), m_callFrame, argument);
2178 setDouble(result);
oliver@apple.com0452e562013-07-25 04:01:40 +00002179 break;
2180 }
commit-queue@webkit.org0ec71072016-08-29 07:21:04 +00002181 }
oliver@apple.com0452e562013-07-25 04:01:40 +00002182 }
msaboff@apple.com95894332014-01-29 19:18:54 +00002183
commit-queue@webkit.orgee8d5482016-08-23 19:09:50 +00002184 void compileArithSin()
2185 {
2186 if (m_node->child1().useKind() == DoubleRepUse) {
2187 setDouble(m_out.doubleSin(lowDouble(m_node->child1())));
2188 return;
2189 }
2190 LValue argument = lowJSValue(m_node->child1());
2191 LValue result = vmCall(Double, m_out.operation(operationArithSin), m_callFrame, argument);
2192 setDouble(result);
2193 }
msaboff@apple.com95894332014-01-29 19:18:54 +00002194
commit-queue@webkit.orgee8d5482016-08-23 19:09:50 +00002195 void compileArithCos()
2196 {
2197 if (m_node->child1().useKind() == DoubleRepUse) {
2198 setDouble(m_out.doubleCos(lowDouble(m_node->child1())));
2199 return;
2200 }
2201 LValue argument = lowJSValue(m_node->child1());
2202 LValue result = vmCall(Double, m_out.operation(operationArithCos), m_callFrame, argument);
2203 setDouble(result);
2204 }
msaboff@apple.com95894332014-01-29 19:18:54 +00002205
utatane.tea@gmail.com9917d6a2016-09-12 22:01:13 +00002206 void compileArithTan()
2207 {
2208 if (m_node->child1().useKind() == DoubleRepUse) {
2209 setDouble(m_out.doubleTan(lowDouble(m_node->child1())));
2210 return;
2211 }
2212 LValue argument = lowJSValue(m_node->child1());
2213 LValue result = vmCall(Double, m_out.operation(operationArithTan), m_callFrame, argument);
2214 setDouble(result);
2215 }
2216
benjamin@webkit.org903025b2015-02-14 04:20:21 +00002217 void compileArithPow()
2218 {
benjamin@webkit.org903025b2015-02-14 04:20:21 +00002219 if (m_node->child2().useKind() == Int32Use)
2220 setDouble(m_out.doublePowi(lowDouble(m_node->child1()), lowInt32(m_node->child2())));
2221 else {
2222 LValue base = lowDouble(m_node->child1());
2223 LValue exponent = lowDouble(m_node->child2());
2224
fpizlo@apple.com91331742016-03-07 02:07:28 +00002225 LBasicBlock integerExponentIsSmallBlock = m_out.newBlock();
2226 LBasicBlock integerExponentPowBlock = m_out.newBlock();
2227 LBasicBlock doubleExponentPowBlockEntry = m_out.newBlock();
fpizlo@apple.com91331742016-03-07 02:07:28 +00002228 LBasicBlock nanExceptionBaseIsOne = m_out.newBlock();
benjamin@webkit.org88d9c892016-04-28 20:50:08 +00002229 LBasicBlock nanExceptionExponentIsInfinity = m_out.newBlock();
2230 LBasicBlock testExponentIsOneHalf = m_out.newBlock();
2231 LBasicBlock handleBaseZeroExponentIsOneHalf = m_out.newBlock();
2232 LBasicBlock handleInfinityForExponentIsOneHalf = m_out.newBlock();
2233 LBasicBlock exponentIsOneHalfNormal = m_out.newBlock();
2234 LBasicBlock exponentIsOneHalfInfinity = m_out.newBlock();
2235 LBasicBlock testExponentIsNegativeOneHalf = m_out.newBlock();
2236 LBasicBlock testBaseZeroExponentIsNegativeOneHalf = m_out.newBlock();
2237 LBasicBlock handleBaseZeroExponentIsNegativeOneHalf = m_out.newBlock();
2238 LBasicBlock handleInfinityForExponentIsNegativeOneHalf = m_out.newBlock();
2239 LBasicBlock exponentIsNegativeOneHalfNormal = m_out.newBlock();
2240 LBasicBlock exponentIsNegativeOneHalfInfinity = m_out.newBlock();
fpizlo@apple.com91331742016-03-07 02:07:28 +00002241 LBasicBlock powBlock = m_out.newBlock();
2242 LBasicBlock nanExceptionResultIsNaN = m_out.newBlock();
2243 LBasicBlock continuation = m_out.newBlock();
benjamin@webkit.org903025b2015-02-14 04:20:21 +00002244
fpizlo@apple.comdae23fb2015-12-21 20:54:51 +00002245 LValue integerExponent = m_out.doubleToInt(exponent);
benjamin@webkit.org903025b2015-02-14 04:20:21 +00002246 LValue integerExponentConvertedToDouble = m_out.intToDouble(integerExponent);
2247 LValue exponentIsInteger = m_out.doubleEqual(exponent, integerExponentConvertedToDouble);
benjamin@webkit.orgff0eef42015-02-19 21:08:21 +00002248 m_out.branch(exponentIsInteger, unsure(integerExponentIsSmallBlock), unsure(doubleExponentPowBlockEntry));
benjamin@webkit.org903025b2015-02-14 04:20:21 +00002249
2250 LBasicBlock lastNext = m_out.appendTo(integerExponentIsSmallBlock, integerExponentPowBlock);
benjamin@webkit.org88d9c892016-04-28 20:50:08 +00002251 LValue integerExponentBelowMax = m_out.belowOrEqual(integerExponent, m_out.constInt32(maxExponentForIntegerMathPow));
2252 m_out.branch(integerExponentBelowMax, usually(integerExponentPowBlock), rarely(doubleExponentPowBlockEntry));
benjamin@webkit.org903025b2015-02-14 04:20:21 +00002253
benjamin@webkit.orgff0eef42015-02-19 21:08:21 +00002254 m_out.appendTo(integerExponentPowBlock, doubleExponentPowBlockEntry);
benjamin@webkit.org903025b2015-02-14 04:20:21 +00002255 ValueFromBlock powDoubleIntResult = m_out.anchor(m_out.doublePowi(base, integerExponent));
2256 m_out.jump(continuation);
2257
benjamin@webkit.org903025b2015-02-14 04:20:21 +00002258 // If y is NaN, the result is NaN.
benjamin@webkit.org88d9c892016-04-28 20:50:08 +00002259 m_out.appendTo(doubleExponentPowBlockEntry, nanExceptionBaseIsOne);
benjamin@webkit.orgff0eef42015-02-19 21:08:21 +00002260 LValue exponentIsNaN;
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00002261 if (provenType(m_node->child2()) & SpecDoubleNaN)
benjamin@webkit.orgff0eef42015-02-19 21:08:21 +00002262 exponentIsNaN = m_out.doubleNotEqualOrUnordered(exponent, exponent);
2263 else
2264 exponentIsNaN = m_out.booleanFalse;
benjamin@webkit.org88d9c892016-04-28 20:50:08 +00002265 m_out.branch(exponentIsNaN, rarely(nanExceptionResultIsNaN), usually(nanExceptionBaseIsOne));
benjamin@webkit.org903025b2015-02-14 04:20:21 +00002266
2267 // If abs(x) is 1 and y is +infinity, the result is NaN.
2268 // If abs(x) is 1 and y is -infinity, the result is NaN.
benjamin@webkit.orgff0eef42015-02-19 21:08:21 +00002269
benjamin@webkit.org88d9c892016-04-28 20:50:08 +00002270 // Test if base == 1.
2271 m_out.appendTo(nanExceptionBaseIsOne, nanExceptionExponentIsInfinity);
benjamin@webkit.org903025b2015-02-14 04:20:21 +00002272 LValue absoluteBase = m_out.doubleAbs(base);
2273 LValue absoluteBaseIsOne = m_out.doubleEqual(absoluteBase, m_out.constDouble(1));
benjamin@webkit.org88d9c892016-04-28 20:50:08 +00002274 m_out.branch(absoluteBaseIsOne, rarely(nanExceptionExponentIsInfinity), usually(testExponentIsOneHalf));
2275
2276 // Test if abs(y) == Infinity.
2277 m_out.appendTo(nanExceptionExponentIsInfinity, testExponentIsOneHalf);
2278 LValue absoluteExponent = m_out.doubleAbs(exponent);
2279 LValue absoluteExponentIsInfinity = m_out.doubleEqual(absoluteExponent, m_out.constDouble(std::numeric_limits<double>::infinity()));
2280 m_out.branch(absoluteExponentIsInfinity, rarely(nanExceptionResultIsNaN), usually(testExponentIsOneHalf));
2281
2282 // If y == 0.5 or y == -0.5, handle it through SQRT.
2283 // We have be carefuly with -0 and -Infinity.
2284
2285 // Test if y == 0.5
2286 m_out.appendTo(testExponentIsOneHalf, handleBaseZeroExponentIsOneHalf);
2287 LValue exponentIsOneHalf = m_out.doubleEqual(exponent, m_out.constDouble(0.5));
2288 m_out.branch(exponentIsOneHalf, rarely(handleBaseZeroExponentIsOneHalf), usually(testExponentIsNegativeOneHalf));
2289
2290 // Handle x == -0.
2291 m_out.appendTo(handleBaseZeroExponentIsOneHalf, handleInfinityForExponentIsOneHalf);
2292 LValue baseIsZeroExponentIsOneHalf = m_out.doubleEqual(base, m_out.doubleZero);
2293 ValueFromBlock zeroResultExponentIsOneHalf = m_out.anchor(m_out.doubleZero);
2294 m_out.branch(baseIsZeroExponentIsOneHalf, rarely(continuation), usually(handleInfinityForExponentIsOneHalf));
2295
2296 // Test if abs(x) == Infinity.
2297 m_out.appendTo(handleInfinityForExponentIsOneHalf, exponentIsOneHalfNormal);
2298 LValue absoluteBaseIsInfinityOneHalf = m_out.doubleEqual(absoluteBase, m_out.constDouble(std::numeric_limits<double>::infinity()));
2299 m_out.branch(absoluteBaseIsInfinityOneHalf, rarely(exponentIsOneHalfInfinity), usually(exponentIsOneHalfNormal));
2300
2301 // The exponent is 0.5, the base is finite or NaN, we can use SQRT.
2302 m_out.appendTo(exponentIsOneHalfNormal, exponentIsOneHalfInfinity);
2303 ValueFromBlock sqrtResult = m_out.anchor(m_out.doubleSqrt(base));
2304 m_out.jump(continuation);
2305
2306 // The exponent is 0.5, the base is infinite, the result is always infinite.
2307 m_out.appendTo(exponentIsOneHalfInfinity, testExponentIsNegativeOneHalf);
2308 ValueFromBlock sqrtInfinityResult = m_out.anchor(m_out.constDouble(std::numeric_limits<double>::infinity()));
2309 m_out.jump(continuation);
2310
2311 // Test if y == -0.5
2312 m_out.appendTo(testExponentIsNegativeOneHalf, testBaseZeroExponentIsNegativeOneHalf);
2313 LValue exponentIsNegativeOneHalf = m_out.doubleEqual(exponent, m_out.constDouble(-0.5));
2314 m_out.branch(exponentIsNegativeOneHalf, rarely(testBaseZeroExponentIsNegativeOneHalf), usually(powBlock));
2315
2316 // Handle x == -0.
2317 m_out.appendTo(testBaseZeroExponentIsNegativeOneHalf, handleBaseZeroExponentIsNegativeOneHalf);
2318 LValue baseIsZeroExponentIsNegativeOneHalf = m_out.doubleEqual(base, m_out.doubleZero);
2319 m_out.branch(baseIsZeroExponentIsNegativeOneHalf, rarely(handleBaseZeroExponentIsNegativeOneHalf), usually(handleInfinityForExponentIsNegativeOneHalf));
2320
2321 m_out.appendTo(handleBaseZeroExponentIsNegativeOneHalf, handleInfinityForExponentIsNegativeOneHalf);
2322 ValueFromBlock oneOverSqrtZeroResult = m_out.anchor(m_out.constDouble(std::numeric_limits<double>::infinity()));
2323 m_out.jump(continuation);
2324
2325 // Test if abs(x) == Infinity.
2326 m_out.appendTo(handleInfinityForExponentIsNegativeOneHalf, exponentIsNegativeOneHalfNormal);
2327 LValue absoluteBaseIsInfinityNegativeOneHalf = m_out.doubleEqual(absoluteBase, m_out.constDouble(std::numeric_limits<double>::infinity()));
2328 m_out.branch(absoluteBaseIsInfinityNegativeOneHalf, rarely(exponentIsNegativeOneHalfInfinity), usually(exponentIsNegativeOneHalfNormal));
2329
2330 // The exponent is -0.5, the base is finite or NaN, we can use 1/SQRT.
2331 m_out.appendTo(exponentIsNegativeOneHalfNormal, exponentIsNegativeOneHalfInfinity);
2332 LValue sqrtBase = m_out.doubleSqrt(base);
2333 ValueFromBlock oneOverSqrtResult = m_out.anchor(m_out.div(m_out.constDouble(1.), sqrtBase));
2334 m_out.jump(continuation);
2335
2336 // The exponent is -0.5, the base is infinite, the result is always zero.
2337 m_out.appendTo(exponentIsNegativeOneHalfInfinity, powBlock);
2338 ValueFromBlock oneOverSqrtInfinityResult = m_out.anchor(m_out.doubleZero);
2339 m_out.jump(continuation);
benjamin@webkit.org903025b2015-02-14 04:20:21 +00002340
benjamin@webkit.orgff0eef42015-02-19 21:08:21 +00002341 m_out.appendTo(powBlock, nanExceptionResultIsNaN);
benjamin@webkit.org903025b2015-02-14 04:20:21 +00002342 ValueFromBlock powResult = m_out.anchor(m_out.doublePow(base, exponent));
2343 m_out.jump(continuation);
2344
benjamin@webkit.orgff0eef42015-02-19 21:08:21 +00002345 m_out.appendTo(nanExceptionResultIsNaN, continuation);
benjamin@webkit.org903025b2015-02-14 04:20:21 +00002346 ValueFromBlock pureNan = m_out.anchor(m_out.constDouble(PNaN));
2347 m_out.jump(continuation);
2348
2349 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00002350 setDouble(m_out.phi(Double, powDoubleIntResult, zeroResultExponentIsOneHalf, sqrtResult, sqrtInfinityResult, oneOverSqrtZeroResult, oneOverSqrtResult, oneOverSqrtInfinityResult, powResult, pureNan));
benjamin@webkit.org903025b2015-02-14 04:20:21 +00002351 }
2352 }
2353
utatane.tea@gmail.comd2fca0a2015-12-15 03:51:42 +00002354 void compileArithRandom()
2355 {
2356 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
2357
2358 // Inlined WeakRandom::advance().
2359 // uint64_t x = m_low;
2360 void* lowAddress = reinterpret_cast<uint8_t*>(globalObject) + JSGlobalObject::weakRandomOffset() + WeakRandom::lowOffset();
2361 LValue low = m_out.load64(m_out.absolute(lowAddress));
2362 // uint64_t y = m_high;
2363 void* highAddress = reinterpret_cast<uint8_t*>(globalObject) + JSGlobalObject::weakRandomOffset() + WeakRandom::highOffset();
2364 LValue high = m_out.load64(m_out.absolute(highAddress));
2365 // m_low = y;
2366 m_out.store64(high, m_out.absolute(lowAddress));
2367
2368 // x ^= x << 23;
2369 LValue phase1 = m_out.bitXor(m_out.shl(low, m_out.constInt64(23)), low);
2370
2371 // x ^= x >> 17;
2372 LValue phase2 = m_out.bitXor(m_out.lShr(phase1, m_out.constInt64(17)), phase1);
2373
2374 // x ^= y ^ (y >> 26);
2375 LValue phase3 = m_out.bitXor(m_out.bitXor(high, m_out.lShr(high, m_out.constInt64(26))), phase2);
2376
2377 // m_high = x;
2378 m_out.store64(phase3, m_out.absolute(highAddress));
2379
2380 // return x + y;
2381 LValue random64 = m_out.add(phase3, high);
2382
2383 // Extract random 53bit. [0, 53] bit is safe integer number ranges in double representation.
2384 LValue random53 = m_out.bitAnd(random64, m_out.constInt64((1ULL << 53) - 1));
2385
2386 LValue double53Integer = m_out.intToDouble(random53);
2387
2388 // Convert `(53bit double integer value) / (1 << 53)` to `(53bit double integer value) * (1.0 / (1 << 53))`.
2389 // In latter case, `1.0 / (1 << 53)` will become a double value represented as (mantissa = 0 & exp = 970, it means 1e-(2**54)).
2390 static const double scale = 1.0 / (1ULL << 53);
2391
2392 // Multiplying 1e-(2**54) with the double integer does not change anything of the mantissa part of the double integer.
2393 // It just reduces the exp part of the given 53bit double integer.
2394 // (Except for 0.0. This is specially handled and in this case, exp just becomes 0.)
2395 // Now we get 53bit precision random double value in [0, 1).
2396 LValue result = m_out.doubleMul(double53Integer, m_out.constDouble(scale));
2397
2398 setDouble(result);
2399 }
2400
benjamin@webkit.orgcb584082015-05-08 00:23:32 +00002401 void compileArithRound()
2402 {
commit-queue@webkit.org2e9df642016-09-20 00:48:39 +00002403 if (m_node->child1().useKind() == DoubleRepUse) {
2404 LValue result = nullptr;
2405 if (producesInteger(m_node->arithRoundingMode()) && !shouldCheckNegativeZero(m_node->arithRoundingMode())) {
2406 LValue value = lowDouble(m_node->child1());
2407 result = m_out.doubleFloor(m_out.doubleAdd(value, m_out.constDouble(0.5)));
2408 } else {
2409 LBasicBlock realPartIsMoreThanHalf = m_out.newBlock();
2410 LBasicBlock continuation = m_out.newBlock();
benjamin@webkit.orgcb584082015-05-08 00:23:32 +00002411
commit-queue@webkit.org2e9df642016-09-20 00:48:39 +00002412 LValue value = lowDouble(m_node->child1());
2413 LValue integerValue = m_out.doubleCeil(value);
2414 ValueFromBlock integerValueResult = m_out.anchor(integerValue);
benjamin@webkit.orgcb584082015-05-08 00:23:32 +00002415
commit-queue@webkit.org2e9df642016-09-20 00:48:39 +00002416 LValue realPart = m_out.doubleSub(integerValue, value);
benjamin@webkit.orgcb584082015-05-08 00:23:32 +00002417
commit-queue@webkit.org2e9df642016-09-20 00:48:39 +00002418 m_out.branch(m_out.doubleGreaterThanOrUnordered(realPart, m_out.constDouble(0.5)), unsure(realPartIsMoreThanHalf), unsure(continuation));
benjamin@webkit.orgcb584082015-05-08 00:23:32 +00002419
commit-queue@webkit.org2e9df642016-09-20 00:48:39 +00002420 LBasicBlock lastNext = m_out.appendTo(realPartIsMoreThanHalf, continuation);
2421 LValue integerValueRoundedDown = m_out.doubleSub(integerValue, m_out.constDouble(1));
2422 ValueFromBlock integerValueRoundedDownResult = m_out.anchor(integerValueRoundedDown);
2423 m_out.jump(continuation);
2424 m_out.appendTo(continuation, lastNext);
benjamin@webkit.orgcb584082015-05-08 00:23:32 +00002425
commit-queue@webkit.org2e9df642016-09-20 00:48:39 +00002426 result = m_out.phi(Double, integerValueResult, integerValueRoundedDownResult);
2427 }
utatane.tea@gmail.com9971c632016-03-01 02:30:46 +00002428
commit-queue@webkit.org2e9df642016-09-20 00:48:39 +00002429 if (producesInteger(m_node->arithRoundingMode())) {
2430 LValue integerValue = convertDoubleToInt32(result, shouldCheckNegativeZero(m_node->arithRoundingMode()));
2431 setInt32(integerValue);
2432 } else
2433 setDouble(result);
2434 return;
utatane.tea@gmail.com9971c632016-03-01 02:30:46 +00002435 }
benjamin@webkit.orgcb584082015-05-08 00:23:32 +00002436
commit-queue@webkit.org2e9df642016-09-20 00:48:39 +00002437 DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == UntypedUse);
2438 LValue argument = lowJSValue(m_node->child1());
2439 setJSValue(vmCall(Int64, m_out.operation(operationArithRound), m_callFrame, argument));
benjamin@webkit.orgcb584082015-05-08 00:23:32 +00002440 }
2441
utatane.tea@gmail.com9971c632016-03-01 02:30:46 +00002442 void compileArithFloor()
2443 {
commit-queue@webkit.org2e9df642016-09-20 00:48:39 +00002444 if (m_node->child1().useKind() == DoubleRepUse) {
2445 LValue value = lowDouble(m_node->child1());
2446 LValue integerValue = m_out.doubleFloor(value);
2447 if (producesInteger(m_node->arithRoundingMode()))
2448 setInt32(convertDoubleToInt32(integerValue, shouldCheckNegativeZero(m_node->arithRoundingMode())));
2449 else
2450 setDouble(integerValue);
2451 return;
2452 }
2453 DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == UntypedUse);
2454 LValue argument = lowJSValue(m_node->child1());
2455 setJSValue(vmCall(Int64, m_out.operation(operationArithFloor), m_callFrame, argument));
utatane.tea@gmail.com9971c632016-03-01 02:30:46 +00002456 }
2457
2458 void compileArithCeil()
2459 {
commit-queue@webkit.org2e9df642016-09-20 00:48:39 +00002460 if (m_node->child1().useKind() == DoubleRepUse) {
2461 LValue value = lowDouble(m_node->child1());
2462 LValue integerValue = m_out.doubleCeil(value);
2463 if (producesInteger(m_node->arithRoundingMode()))
2464 setInt32(convertDoubleToInt32(integerValue, shouldCheckNegativeZero(m_node->arithRoundingMode())));
2465 else
2466 setDouble(integerValue);
2467 return;
2468 }
2469 DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == UntypedUse);
2470 LValue argument = lowJSValue(m_node->child1());
2471 setJSValue(vmCall(Int64, m_out.operation(operationArithCeil), m_callFrame, argument));
utatane.tea@gmail.com9971c632016-03-01 02:30:46 +00002472 }
2473
utatane.tea@gmail.com9b9f43e2016-04-03 08:37:26 +00002474 void compileArithTrunc()
2475 {
commit-queue@webkit.org2e9df642016-09-20 00:48:39 +00002476 if (m_node->child1().useKind() == DoubleRepUse) {
2477 LValue value = lowDouble(m_node->child1());
2478 LValue result = m_out.doubleTrunc(value);
2479 if (producesInteger(m_node->arithRoundingMode()))
2480 setInt32(convertDoubleToInt32(result, shouldCheckNegativeZero(m_node->arithRoundingMode())));
2481 else
2482 setDouble(result);
2483 return;
2484 }
2485 DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == UntypedUse);
2486 LValue argument = lowJSValue(m_node->child1());
2487 setJSValue(vmCall(Int64, m_out.operation(operationArithTrunc), m_callFrame, argument));
utatane.tea@gmail.com9b9f43e2016-04-03 08:37:26 +00002488 }
2489
commit-queue@webkit.org91b902c2016-08-20 02:00:44 +00002490 void compileArithSqrt()
2491 {
2492 if (m_node->child1().useKind() == DoubleRepUse) {
2493 setDouble(m_out.doubleSqrt(lowDouble(m_node->child1())));
2494 return;
2495 }
2496 LValue argument = lowJSValue(m_node->child1());
2497 LValue result = vmCall(Double, m_out.operation(operationArithSqrt), m_callFrame, argument);
2498 setDouble(result);
2499 }
benjamin@webkit.org2b5682d2015-03-04 22:39:28 +00002500
benjamin@webkit.org770c27f2016-08-24 02:36:40 +00002501 void compileArithLog()
2502 {
2503 if (m_node->child1().useKind() == DoubleRepUse) {
2504 setDouble(m_out.doubleLog(lowDouble(m_node->child1())));
2505 return;
2506 }
2507 LValue argument = lowJSValue(m_node->child1());
2508 LValue result = vmCall(Double, m_out.operation(operationArithLog), m_callFrame, argument);
2509 setDouble(result);
2510 }
oliver@apple.com0452e562013-07-25 04:01:40 +00002511
fpizlo@apple.comc5919412014-04-12 23:01:33 +00002512 void compileArithFRound()
2513 {
benjamin@webkit.org87238e92016-08-25 01:21:43 +00002514 if (m_node->child1().useKind() == DoubleRepUse) {
2515 setDouble(m_out.fround(lowDouble(m_node->child1())));
2516 return;
2517 }
2518 LValue argument = lowJSValue(m_node->child1());
2519 LValue result = vmCall(Double, m_out.operation(operationArithFRound), m_callFrame, argument);
2520 setDouble(result);
fpizlo@apple.comc5919412014-04-12 23:01:33 +00002521 }
2522
oliver@apple.comea771492013-07-25 03:58:38 +00002523 void compileArithNegate()
2524 {
2525 switch (m_node->child1().useKind()) {
2526 case Int32Use: {
2527 LValue value = lowInt32(m_node->child1());
2528
msaboff@apple.com95894332014-01-29 19:18:54 +00002529 LValue result;
2530 if (!shouldCheckOverflow(m_node->arithMode()))
2531 result = m_out.neg(value);
2532 else if (!shouldCheckNegativeZero(m_node->arithMode())) {
fpizlo@apple.come158c252016-01-05 21:25:47 +00002533 CheckValue* check = m_out.speculateSub(m_out.int32Zero, value);
2534 blessSpeculation(check, Overflow, noValue(), nullptr, m_origin);
2535 result = check;
msaboff@apple.com95894332014-01-29 19:18:54 +00002536 } else {
2537 speculate(Overflow, noValue(), 0, m_out.testIsZero32(value, m_out.constInt32(0x7fffffff)));
2538 result = m_out.neg(value);
oliver@apple.comea771492013-07-25 03:58:38 +00002539 }
commit-queue@webkit.org0e3c2682013-10-01 23:18:47 +00002540
oliver@apple.com827d2cf2013-07-25 04:04:45 +00002541 setInt32(result);
oliver@apple.comea771492013-07-25 03:58:38 +00002542 break;
2543 }
2544
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00002545 case Int52RepUse: {
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00002546 if (!abstractValue(m_node->child1()).couldBeType(SpecInt52Only)) {
fpizlo@apple.com6921b292013-09-18 17:14:02 +00002547 Int52Kind kind;
2548 LValue value = lowWhicheverInt52(m_node->child1(), kind);
2549 LValue result = m_out.neg(value);
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +00002550 if (shouldCheckNegativeZero(m_node->arithMode()))
fpizlo@apple.com6921b292013-09-18 17:14:02 +00002551 speculate(NegativeZero, noValue(), 0, m_out.isZero64(result));
2552 setInt52(result, kind);
2553 break;
2554 }
2555
2556 LValue value = lowInt52(m_node->child1());
fpizlo@apple.come158c252016-01-05 21:25:47 +00002557 CheckValue* result = m_out.speculateSub(m_out.int64Zero, value);
2558 blessSpeculation(result, Int52Overflow, noValue(), nullptr, m_origin);
fpizlo@apple.com6921b292013-09-18 17:14:02 +00002559 speculate(NegativeZero, noValue(), 0, m_out.isZero64(result));
2560 setInt52(result);
2561 break;
2562 }
2563
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00002564 case DoubleRepUse: {
oliver@apple.com827d2cf2013-07-25 04:04:45 +00002565 setDouble(m_out.doubleNeg(lowDouble(m_node->child1())));
oliver@apple.com32295c12013-07-25 03:59:06 +00002566 break;
2567 }
2568
oliver@apple.comea771492013-07-25 03:58:38 +00002569 default:
commit-queue@webkit.orgf59f0ed2016-10-15 02:19:16 +00002570 DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == UntypedUse);
2571 ArithProfile* arithProfile = m_ftlState.graph.baselineCodeBlockFor(m_node->origin.semantic)->arithProfileForBytecodeOffset(m_node->origin.semantic.bytecodeIndex);
2572 JITNegIC* negIC = codeBlock()->addJITNegIC(arithProfile);
2573 auto repatchingFunction = operationArithNegateOptimize;
2574 auto nonRepatchingFunction = operationArithNegate;
2575 compileMathIC(negIC, repatchingFunction, nonRepatchingFunction);
oliver@apple.comea771492013-07-25 03:58:38 +00002576 break;
2577 }
2578 }
2579
2580 void compileBitAnd()
2581 {
fpizlo@apple.comfee31e22016-01-04 22:31:45 +00002582 if (m_node->isBinaryUseKind(UntypedUse)) {
fpizlo@apple.comfee31e22016-01-04 22:31:45 +00002583 emitBinaryBitOpSnippet<JITBitAndGenerator>(operationValueBitAnd);
mark.lam@apple.comc0008652015-12-15 21:19:31 +00002584 return;
2585 }
oliver@apple.com827d2cf2013-07-25 04:04:45 +00002586 setInt32(m_out.bitAnd(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
oliver@apple.comea771492013-07-25 03:58:38 +00002587 }
2588
2589 void compileBitOr()
2590 {
fpizlo@apple.com905e5722016-01-04 23:08:32 +00002591 if (m_node->isBinaryUseKind(UntypedUse)) {
fpizlo@apple.com905e5722016-01-04 23:08:32 +00002592 emitBinaryBitOpSnippet<JITBitOrGenerator>(operationValueBitOr);
mark.lam@apple.comc0008652015-12-15 21:19:31 +00002593 return;
2594 }
oliver@apple.com827d2cf2013-07-25 04:04:45 +00002595 setInt32(m_out.bitOr(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
oliver@apple.comea771492013-07-25 03:58:38 +00002596 }
2597
2598 void compileBitXor()
2599 {
fpizlo@apple.com905e5722016-01-04 23:08:32 +00002600 if (m_node->isBinaryUseKind(UntypedUse)) {
fpizlo@apple.com905e5722016-01-04 23:08:32 +00002601 emitBinaryBitOpSnippet<JITBitXorGenerator>(operationValueBitXor);
mark.lam@apple.comc0008652015-12-15 21:19:31 +00002602 return;
2603 }
oliver@apple.com827d2cf2013-07-25 04:04:45 +00002604 setInt32(m_out.bitXor(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
oliver@apple.comea771492013-07-25 03:58:38 +00002605 }
2606
2607 void compileBitRShift()
2608 {
fpizlo@apple.com905e5722016-01-04 23:08:32 +00002609 if (m_node->isBinaryUseKind(UntypedUse)) {
fpizlo@apple.com905e5722016-01-04 23:08:32 +00002610 emitRightShiftSnippet(JITRightShiftGenerator::SignedShift);
mark.lam@apple.comc0008652015-12-15 21:19:31 +00002611 return;
2612 }
oliver@apple.com827d2cf2013-07-25 04:04:45 +00002613 setInt32(m_out.aShr(
2614 lowInt32(m_node->child1()),
2615 m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
oliver@apple.comea771492013-07-25 03:58:38 +00002616 }
2617
2618 void compileBitLShift()
2619 {
fpizlo@apple.com905e5722016-01-04 23:08:32 +00002620 if (m_node->isBinaryUseKind(UntypedUse)) {
fpizlo@apple.com905e5722016-01-04 23:08:32 +00002621 emitBinaryBitOpSnippet<JITLeftShiftGenerator>(operationValueBitLShift);
mark.lam@apple.comc0008652015-12-15 21:19:31 +00002622 return;
2623 }
oliver@apple.com827d2cf2013-07-25 04:04:45 +00002624 setInt32(m_out.shl(
2625 lowInt32(m_node->child1()),
2626 m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
oliver@apple.comea771492013-07-25 03:58:38 +00002627 }
2628
2629 void compileBitURShift()
2630 {
fpizlo@apple.com905e5722016-01-04 23:08:32 +00002631 if (m_node->isBinaryUseKind(UntypedUse)) {
fpizlo@apple.com905e5722016-01-04 23:08:32 +00002632 emitRightShiftSnippet(JITRightShiftGenerator::UnsignedShift);
mark.lam@apple.comc0008652015-12-15 21:19:31 +00002633 return;
2634 }
oliver@apple.com827d2cf2013-07-25 04:04:45 +00002635 setInt32(m_out.lShr(
2636 lowInt32(m_node->child1()),
2637 m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
oliver@apple.comea771492013-07-25 03:58:38 +00002638 }
2639
2640 void compileUInt32ToNumber()
2641 {
oliver@apple.com32295c12013-07-25 03:59:06 +00002642 LValue value = lowInt32(m_node->child1());
2643
fpizlo@apple.coma0fb09052014-01-07 04:52:48 +00002644 if (doesOverflow(m_node->arithMode())) {
commit-queue@webkit.orge086f372016-04-08 18:07:25 +00002645 setStrictInt52(m_out.zeroExtPtr(value));
oliver@apple.comea771492013-07-25 03:58:38 +00002646 return;
2647 }
commit-queue@webkit.orge086f372016-04-08 18:07:25 +00002648
fpizlo@apple.com9089acb2013-12-14 06:33:42 +00002649 speculate(Overflow, noValue(), 0, m_out.lessThan(value, m_out.int32Zero));
oliver@apple.com827d2cf2013-07-25 04:04:45 +00002650 setInt32(value);
oliver@apple.comea771492013-07-25 03:58:38 +00002651 }
2652
2653 void compileCheckStructure()
2654 {
oliver@apple.comea771492013-07-25 03:58:38 +00002655 ExitKind exitKind;
fpizlo@apple.comb41e6822014-07-25 20:55:17 +00002656 if (m_node->child1()->hasConstant())
2657 exitKind = BadConstantCache;
oliver@apple.comea771492013-07-25 03:58:38 +00002658 else
2659 exitKind = BadCache;
fpizlo@apple.com12835772015-09-21 20:49:04 +00002660
2661 switch (m_node->child1().useKind()) {
2662 case CellUse:
2663 case KnownCellUse: {
2664 LValue cell = lowCell(m_node->child1());
2665
2666 checkStructure(
2667 m_out.load32(cell, m_heaps.JSCell_structureID), jsValueValue(cell),
2668 exitKind, m_node->structureSet(),
sbarati@apple.com239d20b2017-01-26 23:50:58 +00002669 [&] (RegisteredStructure structure) {
fpizlo@apple.com12835772015-09-21 20:49:04 +00002670 return weakStructureID(structure);
2671 });
2672 return;
2673 }
2674
2675 case CellOrOtherUse: {
2676 LValue value = lowJSValue(m_node->child1(), ManualOperandSpeculation);
2677
fpizlo@apple.com91331742016-03-07 02:07:28 +00002678 LBasicBlock cellCase = m_out.newBlock();
2679 LBasicBlock notCellCase = m_out.newBlock();
2680 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com12835772015-09-21 20:49:04 +00002681
2682 m_out.branch(
2683 isCell(value, provenType(m_node->child1())), unsure(cellCase), unsure(notCellCase));
2684
2685 LBasicBlock lastNext = m_out.appendTo(cellCase, notCellCase);
2686 checkStructure(
2687 m_out.load32(value, m_heaps.JSCell_structureID), jsValueValue(value),
2688 exitKind, m_node->structureSet(),
sbarati@apple.com239d20b2017-01-26 23:50:58 +00002689 [&] (RegisteredStructure structure) {
fpizlo@apple.com12835772015-09-21 20:49:04 +00002690 return weakStructureID(structure);
2691 });
2692 m_out.jump(continuation);
2693
2694 m_out.appendTo(notCellCase, continuation);
2695 FTL_TYPE_CHECK(jsValueValue(value), m_node->child1(), SpecCell | SpecOther, isNotOther(value));
2696 m_out.jump(continuation);
2697
2698 m_out.appendTo(continuation, lastNext);
2699 return;
2700 }
2701
2702 default:
2703 DFG_CRASH(m_graph, m_node, "Bad use kind");
2704 return;
2705 }
oliver@apple.comea771492013-07-25 03:58:38 +00002706 }
2707
fpizlo@apple.com29abafe2014-08-28 19:09:48 +00002708 void compileCheckCell()
fpizlo@apple.comfb813db2013-11-07 05:38:16 +00002709 {
2710 LValue cell = lowCell(m_node->child1());
2711
2712 speculate(
fpizlo@apple.com29abafe2014-08-28 19:09:48 +00002713 BadCell, jsValueValue(cell), m_node->child1().node(),
fpizlo@apple.com96c1c4b2015-03-04 06:55:52 +00002714 m_out.notEqual(cell, weakPointer(m_node->cellOperand()->cell())));
fpizlo@apple.comfb813db2013-11-07 05:38:16 +00002715 }
2716
fpizlo@apple.com29abafe2014-08-28 19:09:48 +00002717 void compileCheckBadCell()
2718 {
2719 terminate(BadCell);
2720 }
rniwa@webkit.orgeb7ac192015-03-13 01:11:15 +00002721
2722 void compileCheckNotEmpty()
2723 {
2724 speculate(TDZFailure, noValue(), nullptr, m_out.isZero64(lowJSValue(m_node->child1())));
2725 }
2726
utatane.tea@gmail.com7f364f22016-07-29 07:15:01 +00002727 void compileCheckStringIdent()
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +00002728 {
2729 UniquedStringImpl* uid = m_node->uidOperand();
sbarati@apple.comd0a8f952016-10-10 20:33:46 +00002730 LValue stringImpl = lowStringIdent(m_node->child1());
utatane.tea@gmail.com7f364f22016-07-29 07:15:01 +00002731 speculate(BadIdent, noValue(), nullptr, m_out.notEqual(stringImpl, m_out.constIntPtr(uid)));
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +00002732 }
2733
fpizlo@apple.com29abafe2014-08-28 19:09:48 +00002734 void compileGetExecutable()
msaboff@apple.com95894332014-01-29 19:18:54 +00002735 {
2736 LValue cell = lowCell(m_node->child1());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002737 speculateFunction(m_node->child1(), cell);
fpizlo@apple.com29abafe2014-08-28 19:09:48 +00002738 setJSValue(m_out.loadPtr(cell, m_heaps.JSFunction_executable));
msaboff@apple.com95894332014-01-29 19:18:54 +00002739 }
2740
oliver@apple.comb0cdcb42013-07-25 04:03:57 +00002741 void compileArrayifyToStructure()
2742 {
2743 LValue cell = lowCell(m_node->child1());
2744 LValue property = !!m_node->child2() ? lowInt32(m_node->child2()) : 0;
2745
fpizlo@apple.com91331742016-03-07 02:07:28 +00002746 LBasicBlock unexpectedStructure = m_out.newBlock();
2747 LBasicBlock continuation = m_out.newBlock();
oliver@apple.comb0cdcb42013-07-25 04:03:57 +00002748
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +00002749 LValue structureID = m_out.load32(cell, m_heaps.JSCell_structureID);
oliver@apple.comb0cdcb42013-07-25 04:03:57 +00002750
2751 m_out.branch(
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00002752 m_out.notEqual(structureID, weakStructureID(m_node->structure())),
fpizlo@apple.com975ae502014-02-19 22:29:43 +00002753 rarely(unexpectedStructure), usually(continuation));
oliver@apple.comb0cdcb42013-07-25 04:03:57 +00002754
2755 LBasicBlock lastNext = m_out.appendTo(unexpectedStructure, continuation);
2756
2757 if (property) {
2758 switch (m_node->arrayMode().type()) {
2759 case Array::Int32:
2760 case Array::Double:
2761 case Array::Contiguous:
2762 speculate(
2763 Uncountable, noValue(), 0,
2764 m_out.aboveOrEqual(property, m_out.constInt32(MIN_SPARSE_ARRAY_INDEX)));
2765 break;
2766 default:
2767 break;
2768 }
2769 }
2770
2771 switch (m_node->arrayMode().type()) {
2772 case Array::Int32:
fpizlo@apple.com994d4532016-07-03 19:34:55 +00002773 vmCall(Void, m_out.operation(operationEnsureInt32), m_callFrame, cell);
oliver@apple.comb0cdcb42013-07-25 04:03:57 +00002774 break;
2775 case Array::Double:
fpizlo@apple.com994d4532016-07-03 19:34:55 +00002776 vmCall(Void, m_out.operation(operationEnsureDouble), m_callFrame, cell);
oliver@apple.comb0cdcb42013-07-25 04:03:57 +00002777 break;
2778 case Array::Contiguous:
fpizlo@apple.com994d4532016-07-03 19:34:55 +00002779 vmCall(Void, m_out.operation(operationEnsureContiguous), m_callFrame, cell);
oliver@apple.comb0cdcb42013-07-25 04:03:57 +00002780 break;
2781 case Array::ArrayStorage:
2782 case Array::SlowPutArrayStorage:
fpizlo@apple.com994d4532016-07-03 19:34:55 +00002783 vmCall(Void, m_out.operation(operationEnsureArrayStorage), m_callFrame, cell);
oliver@apple.comb0cdcb42013-07-25 04:03:57 +00002784 break;
2785 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00002786 DFG_CRASH(m_graph, m_node, "Bad array type");
2787 break;
oliver@apple.comb0cdcb42013-07-25 04:03:57 +00002788 }
2789
fpizlo@apple.com6b5d7302014-03-16 16:49:16 +00002790 structureID = m_out.load32(cell, m_heaps.JSCell_structureID);
oliver@apple.comb0cdcb42013-07-25 04:03:57 +00002791 speculate(
2792 BadIndexingType, jsValueValue(cell), 0,
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00002793 m_out.notEqual(structureID, weakStructureID(m_node->structure())));
oliver@apple.comb0cdcb42013-07-25 04:03:57 +00002794 m_out.jump(continuation);
2795
2796 m_out.appendTo(continuation, lastNext);
2797 }
2798
oliver@apple.comea771492013-07-25 03:58:38 +00002799 void compilePutStructure()
2800 {
fpizlo@apple.com67aa4052013-08-23 19:41:54 +00002801 m_ftlState.jitCode->common.notifyCompilingStructureTransition(m_graph.m_plan, codeBlock(), m_node);
fpizlo@apple.com101a1682016-11-15 01:49:22 +00002802
sbarati@apple.com239d20b2017-01-26 23:50:58 +00002803 RegisteredStructure oldStructure = m_node->transition()->previous;
2804 RegisteredStructure newStructure = m_node->transition()->next;
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +00002805 ASSERT_UNUSED(oldStructure, oldStructure->indexingType() == newStructure->indexingType());
2806 ASSERT(oldStructure->typeInfo().inlineTypeFlags() == newStructure->typeInfo().inlineTypeFlags());
2807 ASSERT(oldStructure->typeInfo().type() == newStructure->typeInfo().type());
2808
2809 LValue cell = lowCell(m_node->child1());
2810 m_out.store32(
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00002811 weakStructureID(newStructure),
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +00002812 cell, m_heaps.JSCell_structureID);
oliver@apple.comea771492013-07-25 03:58:38 +00002813 }
2814
keith_miller@apple.com7deaba82016-04-10 03:38:44 +00002815 void compileGetById(AccessType type)
fpizlo@apple.com6cd705d2013-10-14 18:08:11 +00002816 {
cdumez@apple.comc412c1d2016-11-11 16:50:57 +00002817 ASSERT(type == AccessType::Get || type == AccessType::GetPure);
fpizlo@apple.coma14dfc02014-01-30 23:00:16 +00002818 switch (m_node->child1().useKind()) {
2819 case CellUse: {
keith_miller@apple.com7deaba82016-04-10 03:38:44 +00002820 setJSValue(getById(lowCell(m_node->child1()), type));
fpizlo@apple.coma14dfc02014-01-30 23:00:16 +00002821 return;
2822 }
2823
2824 case UntypedUse: {
2825 // This is pretty weird, since we duplicate the slow path both here and in the
2826 // code generated by the IC. We should investigate making this less bad.
2827 // https://bugs.webkit.org/show_bug.cgi?id=127830
2828 LValue value = lowJSValue(m_node->child1());
2829
fpizlo@apple.com91331742016-03-07 02:07:28 +00002830 LBasicBlock cellCase = m_out.newBlock();
2831 LBasicBlock notCellCase = m_out.newBlock();
2832 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.coma14dfc02014-01-30 23:00:16 +00002833
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00002834 m_out.branch(
2835 isCell(value, provenType(m_node->child1())), unsure(cellCase), unsure(notCellCase));
fpizlo@apple.coma14dfc02014-01-30 23:00:16 +00002836
2837 LBasicBlock lastNext = m_out.appendTo(cellCase, notCellCase);
keith_miller@apple.com7deaba82016-04-10 03:38:44 +00002838 ValueFromBlock cellResult = m_out.anchor(getById(value, type));
fpizlo@apple.coma14dfc02014-01-30 23:00:16 +00002839 m_out.jump(continuation);
keith_miller@apple.com7deaba82016-04-10 03:38:44 +00002840
2841 J_JITOperation_EJI getByIdFunction;
2842 if (type == AccessType::Get)
2843 getByIdFunction = operationGetByIdGeneric;
2844 else
2845 getByIdFunction = operationTryGetByIdGeneric;
2846
fpizlo@apple.coma14dfc02014-01-30 23:00:16 +00002847 m_out.appendTo(notCellCase, continuation);
2848 ValueFromBlock notCellResult = m_out.anchor(vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00002849 Int64, m_out.operation(getByIdFunction),
fpizlo@apple.com4d04f3c2015-06-03 20:04:00 +00002850 m_callFrame, value,
fpizlo@apple.coma14dfc02014-01-30 23:00:16 +00002851 m_out.constIntPtr(m_graph.identifiers()[m_node->identifierNumber()])));
2852 m_out.jump(continuation);
2853
2854 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00002855 setJSValue(m_out.phi(Int64, cellResult, notCellResult));
fpizlo@apple.coma14dfc02014-01-30 23:00:16 +00002856 return;
2857 }
2858
2859 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00002860 DFG_CRASH(m_graph, m_node, "Bad use kind");
fpizlo@apple.coma14dfc02014-01-30 23:00:16 +00002861 return;
2862 }
fpizlo@apple.com6cd705d2013-10-14 18:08:11 +00002863 }
sbarati@apple.com23315d62016-05-09 20:17:23 +00002864
2865 void compileGetByIdWithThis()
2866 {
2867 LValue base = lowJSValue(m_node->child1());
2868 LValue thisValue = lowJSValue(m_node->child2());
fpizlo@apple.com994d4532016-07-03 19:34:55 +00002869 LValue result = vmCall(Int64, m_out.operation(operationGetByIdWithThis), m_callFrame, base, thisValue, m_out.constIntPtr(m_graph.identifiers()[m_node->identifierNumber()]));
sbarati@apple.com23315d62016-05-09 20:17:23 +00002870 setJSValue(result);
2871 }
2872
2873 void compileGetByValWithThis()
2874 {
2875 LValue base = lowJSValue(m_node->child1());
2876 LValue thisValue = lowJSValue(m_node->child2());
2877 LValue subscript = lowJSValue(m_node->child3());
2878
fpizlo@apple.com994d4532016-07-03 19:34:55 +00002879 LValue result = vmCall(Int64, m_out.operation(operationGetByValWithThis), m_callFrame, base, thisValue, subscript);
sbarati@apple.com23315d62016-05-09 20:17:23 +00002880 setJSValue(result);
2881 }
2882
2883 void compilePutByIdWithThis()
2884 {
2885 LValue base = lowJSValue(m_node->child1());
2886 LValue thisValue = lowJSValue(m_node->child2());
2887 LValue value = lowJSValue(m_node->child3());
2888
fpizlo@apple.com994d4532016-07-03 19:34:55 +00002889 vmCall(Void, m_out.operation(m_graph.isStrictModeFor(m_node->origin.semantic) ? operationPutByIdWithThisStrict : operationPutByIdWithThis),
sbarati@apple.com23315d62016-05-09 20:17:23 +00002890 m_callFrame, base, thisValue, value, m_out.constIntPtr(m_graph.identifiers()[m_node->identifierNumber()]));
2891 }
2892
2893 void compilePutByValWithThis()
2894 {
2895 LValue base = lowJSValue(m_graph.varArgChild(m_node, 0));
2896 LValue thisValue = lowJSValue(m_graph.varArgChild(m_node, 1));
2897 LValue property = lowJSValue(m_graph.varArgChild(m_node, 2));
2898 LValue value = lowJSValue(m_graph.varArgChild(m_node, 3));
2899
fpizlo@apple.com994d4532016-07-03 19:34:55 +00002900 vmCall(Void, m_out.operation(m_graph.isStrictModeFor(m_node->origin.semantic) ? operationPutByValWithThisStrict : operationPutByValWithThis),
sbarati@apple.com23315d62016-05-09 20:17:23 +00002901 m_callFrame, base, thisValue, property, value);
2902 }
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +00002903
2904 void compileDefineDataProperty()
2905 {
2906 LValue base = lowCell(m_graph.varArgChild(m_node, 0));
2907 LValue value = lowJSValue(m_graph.varArgChild(m_node, 2));
2908 LValue attributes = lowInt32(m_graph.varArgChild(m_node, 3));
2909 Edge& propertyEdge = m_graph.varArgChild(m_node, 1);
2910 switch (propertyEdge.useKind()) {
2911 case StringUse: {
2912 LValue property = lowString(propertyEdge);
2913 vmCall(Void, m_out.operation(operationDefineDataPropertyString), m_callFrame, base, property, value, attributes);
2914 break;
2915 }
2916 case StringIdentUse: {
2917 LValue property = lowStringIdent(propertyEdge);
2918 vmCall(Void, m_out.operation(operationDefineDataPropertyStringIdent), m_callFrame, base, property, value, attributes);
2919 break;
2920 }
2921 case SymbolUse: {
2922 LValue property = lowSymbol(propertyEdge);
2923 vmCall(Void, m_out.operation(operationDefineDataPropertySymbol), m_callFrame, base, property, value, attributes);
2924 break;
2925 }
2926 case UntypedUse: {
2927 LValue property = lowJSValue(propertyEdge);
2928 vmCall(Void, m_out.operation(operationDefineDataProperty), m_callFrame, base, property, value, attributes);
2929 break;
2930 }
2931 default:
2932 RELEASE_ASSERT_NOT_REACHED();
2933 }
2934 }
2935
2936 void compileDefineAccessorProperty()
2937 {
2938 LValue base = lowCell(m_graph.varArgChild(m_node, 0));
2939 LValue getter = lowCell(m_graph.varArgChild(m_node, 2));
2940 LValue setter = lowCell(m_graph.varArgChild(m_node, 3));
2941 LValue attributes = lowInt32(m_graph.varArgChild(m_node, 4));
2942 Edge& propertyEdge = m_graph.varArgChild(m_node, 1);
2943 switch (propertyEdge.useKind()) {
2944 case StringUse: {
2945 LValue property = lowString(propertyEdge);
2946 vmCall(Void, m_out.operation(operationDefineAccessorPropertyString), m_callFrame, base, property, getter, setter, attributes);
2947 break;
2948 }
2949 case StringIdentUse: {
2950 LValue property = lowStringIdent(propertyEdge);
2951 vmCall(Void, m_out.operation(operationDefineAccessorPropertyStringIdent), m_callFrame, base, property, getter, setter, attributes);
2952 break;
2953 }
2954 case SymbolUse: {
2955 LValue property = lowSymbol(propertyEdge);
2956 vmCall(Void, m_out.operation(operationDefineAccessorPropertySymbol), m_callFrame, base, property, getter, setter, attributes);
2957 break;
2958 }
2959 case UntypedUse: {
2960 LValue property = lowJSValue(propertyEdge);
2961 vmCall(Void, m_out.operation(operationDefineAccessorProperty), m_callFrame, base, property, getter, setter, attributes);
2962 break;
2963 }
2964 default:
2965 RELEASE_ASSERT_NOT_REACHED();
2966 }
2967 }
fpizlo@apple.com6cd705d2013-10-14 18:08:11 +00002968
fpizlo@apple.com87839ab2013-11-05 18:56:06 +00002969 void compilePutById()
2970 {
commit-queue@webkit.org5d428a22016-09-02 23:13:50 +00002971 DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == CellUse);
fpizlo@apple.com9d2d8b22015-12-14 23:18:36 +00002972
commit-queue@webkit.org5d428a22016-09-02 23:13:50 +00002973 Node* node = m_node;
fpizlo@apple.com9d2d8b22015-12-14 23:18:36 +00002974 LValue base = lowCell(node->child1());
2975 LValue value = lowJSValue(node->child2());
2976 auto uid = m_graph.identifiers()[node->identifierNumber()];
benjamin@webkit.org81ec96c2015-11-18 23:14:54 +00002977
fpizlo@apple.com9d2d8b22015-12-14 23:18:36 +00002978 B3::PatchpointValue* patchpoint = m_out.patchpoint(Void);
fpizlo@apple.com45e45652016-01-07 21:20:37 +00002979 patchpoint->appendSomeRegister(base);
2980 patchpoint->appendSomeRegister(value);
fpizlo@apple.com4d03e0e2016-04-18 17:13:33 +00002981 patchpoint->append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister));
2982 patchpoint->append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister));
fpizlo@apple.com9d2d8b22015-12-14 23:18:36 +00002983 patchpoint->clobber(RegisterSet::macroScratchRegisters());
2984
fpizlo@apple.com05b1b222016-01-07 22:59:43 +00002985 // FIXME: If this is a PutByIdFlush, we might want to late-clobber volatile registers.
2986 // https://bugs.webkit.org/show_bug.cgi?id=152848
2987
2988 RefPtr<PatchpointExceptionHandle> exceptionHandle =
2989 preparePatchpointForExceptions(patchpoint);
2990
fpizlo@apple.com9d2d8b22015-12-14 23:18:36 +00002991 State* state = &m_ftlState;
2992 ECMAMode ecmaMode = m_graph.executableFor(node->origin.semantic)->ecmaMode();
2993
2994 patchpoint->setGenerator(
2995 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
2996 AllowMacroScratchRegisterUsage allowScratch(jit);
2997
fpizlo@apple.com05b1b222016-01-07 22:59:43 +00002998 CallSiteIndex callSiteIndex =
2999 state->jitCode->common.addUniqueCallSiteIndex(node->origin.semantic);
3000
3001 Box<CCallHelpers::JumpList> exceptions =
3002 exceptionHandle->scheduleExitCreation(params)->jumps(jit);
3003
3004 // JS setter call ICs generated by the PutById IC will need this.
3005 exceptionHandle->scheduleExitCreationForUnwind(params, callSiteIndex);
3006
fpizlo@apple.com9d2d8b22015-12-14 23:18:36 +00003007 auto generator = Box<JITPutByIdGenerator>::create(
fpizlo@apple.com05b1b222016-01-07 22:59:43 +00003008 jit.codeBlock(), node->origin.semantic, callSiteIndex,
fpizlo@apple.com86cbf132015-12-28 22:46:51 +00003009 params.unavailableRegisters(), JSValueRegs(params[0].gpr()),
3010 JSValueRegs(params[1].gpr()), GPRInfo::patchpointScratchRegister, ecmaMode,
fpizlo@apple.com9d2d8b22015-12-14 23:18:36 +00003011 node->op() == PutByIdDirect ? Direct : NotDirect);
3012
3013 generator->generateFastPath(jit);
3014 CCallHelpers::Label done = jit.label();
3015
3016 params.addLatePath(
3017 [=] (CCallHelpers& jit) {
3018 AllowMacroScratchRegisterUsage allowScratch(jit);
3019
fpizlo@apple.com9d2d8b22015-12-14 23:18:36 +00003020 generator->slowPathJump().link(&jit);
3021 CCallHelpers::Label slowPathBegin = jit.label();
3022 CCallHelpers::Call slowPathCall = callOperation(
fpizlo@apple.com86cbf132015-12-28 22:46:51 +00003023 *state, params.unavailableRegisters(), jit, node->origin.semantic,
fpizlo@apple.com05b1b222016-01-07 22:59:43 +00003024 exceptions.get(), generator->slowPathFunction(), InvalidGPRReg,
fpizlo@apple.com9d2d8b22015-12-14 23:18:36 +00003025 CCallHelpers::TrustedImmPtr(generator->stubInfo()), params[1].gpr(),
3026 params[0].gpr(), CCallHelpers::TrustedImmPtr(uid)).call();
3027 jit.jump().linkTo(done, &jit);
3028
3029 generator->reportSlowPathCall(slowPathBegin, slowPathCall);
3030
3031 jit.addLinkTask(
3032 [=] (LinkBuffer& linkBuffer) {
3033 generator->finalize(linkBuffer);
3034 });
3035 });
3036 });
fpizlo@apple.com87839ab2013-11-05 18:56:06 +00003037 }
3038
oliver@apple.comea771492013-07-25 03:58:38 +00003039 void compileGetButterfly()
3040 {
fpizlo@apple.com95ef6492016-03-15 15:26:36 +00003041 setStorage(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSObject_butterfly));
fpizlo@apple.com8dde06b2015-10-12 22:41:01 +00003042 }
3043
fpizlo@apple.com9ca951e2013-12-09 01:08:53 +00003044 void compileConstantStoragePointer()
3045 {
3046 setStorage(m_out.constIntPtr(m_node->storagePointer()));
3047 }
3048
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +00003049 void compileGetIndexedPropertyStorage()
3050 {
fpizlo@apple.com86897bf2013-11-06 02:07:43 +00003051 LValue cell = lowCell(m_node->child1());
3052
3053 if (m_node->arrayMode().type() == Array::String) {
fpizlo@apple.com91331742016-03-07 02:07:28 +00003054 LBasicBlock slowPath = m_out.newBlock();
3055 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com373ed6b2015-12-15 04:52:55 +00003056
3057 LValue fastResultValue = m_out.loadPtr(cell, m_heaps.JSString_value);
3058 ValueFromBlock fastResult = m_out.anchor(fastResultValue);
fpizlo@apple.com86897bf2013-11-06 02:07:43 +00003059
fpizlo@apple.com975ae502014-02-19 22:29:43 +00003060 m_out.branch(
fpizlo@apple.com373ed6b2015-12-15 04:52:55 +00003061 m_out.notNull(fastResultValue), usually(continuation), rarely(slowPath));
fpizlo@apple.com86897bf2013-11-06 02:07:43 +00003062
3063 LBasicBlock lastNext = m_out.appendTo(slowPath, continuation);
3064
3065 ValueFromBlock slowResult = m_out.anchor(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00003066 vmCall(pointerType(), m_out.operation(operationResolveRope), m_callFrame, cell));
fpizlo@apple.com86897bf2013-11-06 02:07:43 +00003067
3068 m_out.jump(continuation);
3069
3070 m_out.appendTo(continuation, lastNext);
3071
fpizlo@apple.com994d4532016-07-03 19:34:55 +00003072 setStorage(m_out.loadPtr(m_out.phi(pointerType(), fastResult, slowResult), m_heaps.StringImpl_data));
fpizlo@apple.com86897bf2013-11-06 02:07:43 +00003073 return;
3074 }
commit-queue@webkit.org5d428a22016-09-02 23:13:50 +00003075
3076 DFG_ASSERT(m_graph, m_node, isTypedView(m_node->arrayMode().typedArrayType()));
fpizlo@apple.com95ef6492016-03-15 15:26:36 +00003077 setStorage(m_out.loadPtr(cell, m_heaps.JSArrayBufferView_vector));
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +00003078 }
3079
3080 void compileCheckArray()
3081 {
3082 Edge edge = m_node->child1();
3083 LValue cell = lowCell(edge);
3084
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00003085 if (m_node->arrayMode().alreadyChecked(m_graph, m_node, abstractValue(edge)))
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +00003086 return;
3087
3088 speculate(
3089 BadIndexingType, jsValueValue(cell), 0,
fpizlo@apple.com959a2c42015-12-22 21:59:59 +00003090 m_out.logicalNot(isArrayType(cell, m_node->arrayMode())));
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +00003091 }
commit-queue@webkit.org4b4fe042014-02-03 21:51:47 +00003092
3093 void compileGetTypedArrayByteOffset()
3094 {
3095 LValue basePtr = lowCell(m_node->child1());
3096
fpizlo@apple.com91331742016-03-07 02:07:28 +00003097 LBasicBlock simpleCase = m_out.newBlock();
3098 LBasicBlock wastefulCase = m_out.newBlock();
3099 LBasicBlock continuation = m_out.newBlock();
commit-queue@webkit.org4b4fe042014-02-03 21:51:47 +00003100
fpizlo@apple.com93373ba2015-04-07 22:09:15 +00003101 LValue mode = m_out.load32(basePtr, m_heaps.JSArrayBufferView_mode);
fpizlo@apple.com975ae502014-02-19 22:29:43 +00003102 m_out.branch(
fpizlo@apple.com93373ba2015-04-07 22:09:15 +00003103 m_out.notEqual(mode, m_out.constInt32(WastefulTypedArray)),
fpizlo@apple.com975ae502014-02-19 22:29:43 +00003104 unsure(simpleCase), unsure(wastefulCase));
commit-queue@webkit.org4b4fe042014-02-03 21:51:47 +00003105
commit-queue@webkit.org4b4fe042014-02-03 21:51:47 +00003106 LBasicBlock lastNext = m_out.appendTo(simpleCase, wastefulCase);
3107
3108 ValueFromBlock simpleOut = m_out.anchor(m_out.constIntPtr(0));
3109
3110 m_out.jump(continuation);
3111
commit-queue@webkit.org4b4fe042014-02-03 21:51:47 +00003112 m_out.appendTo(wastefulCase, continuation);
3113
fpizlo@apple.com95ef6492016-03-15 15:26:36 +00003114 LValue vectorPtr = m_out.loadPtr(basePtr, m_heaps.JSArrayBufferView_vector);
3115 LValue butterflyPtr = m_out.loadPtr(basePtr, m_heaps.JSObject_butterfly);
commit-queue@webkit.org4b4fe042014-02-03 21:51:47 +00003116 LValue arrayBufferPtr = m_out.loadPtr(butterflyPtr, m_heaps.Butterfly_arrayBuffer);
3117 LValue dataPtr = m_out.loadPtr(arrayBufferPtr, m_heaps.ArrayBuffer_data);
3118
fpizlo@apple.com93373ba2015-04-07 22:09:15 +00003119 ValueFromBlock wastefulOut = m_out.anchor(m_out.sub(vectorPtr, dataPtr));
commit-queue@webkit.org4b4fe042014-02-03 21:51:47 +00003120
3121 m_out.jump(continuation);
3122 m_out.appendTo(continuation, lastNext);
3123
fpizlo@apple.com994d4532016-07-03 19:34:55 +00003124 setInt32(m_out.castToInt32(m_out.phi(pointerType(), simpleOut, wastefulOut)));
commit-queue@webkit.org4b4fe042014-02-03 21:51:47 +00003125 }
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +00003126
oliver@apple.comea771492013-07-25 03:58:38 +00003127 void compileGetArrayLength()
3128 {
3129 switch (m_node->arrayMode().type()) {
commit-queue@webkit.orgb4bf63e2016-09-12 22:13:37 +00003130 case Array::Undecided:
oliver@apple.comea771492013-07-25 03:58:38 +00003131 case Array::Int32:
3132 case Array::Double:
3133 case Array::Contiguous: {
msaboff@apple.com95894332014-01-29 19:18:54 +00003134 setInt32(m_out.load32NonNegative(lowStorage(m_node->child2()), m_heaps.Butterfly_publicLength));
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +00003135 return;
oliver@apple.comea771492013-07-25 03:58:38 +00003136 }
3137
fpizlo@apple.com86897bf2013-11-06 02:07:43 +00003138 case Array::String: {
3139 LValue string = lowCell(m_node->child1());
msaboff@apple.com95894332014-01-29 19:18:54 +00003140 setInt32(m_out.load32NonNegative(string, m_heaps.JSString_length));
fpizlo@apple.com86897bf2013-11-06 02:07:43 +00003141 return;
3142 }
3143
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003144 case Array::DirectArguments: {
3145 LValue arguments = lowCell(m_node->child1());
3146 speculate(
3147 ExoticObjectMode, noValue(), nullptr,
commit-queue@webkit.org812d82a2016-12-24 21:26:22 +00003148 m_out.notNull(m_out.loadPtr(arguments, m_heaps.DirectArguments_mappedArguments)));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003149 setInt32(m_out.load32NonNegative(arguments, m_heaps.DirectArguments_length));
3150 return;
3151 }
3152
3153 case Array::ScopedArguments: {
3154 LValue arguments = lowCell(m_node->child1());
3155 speculate(
3156 ExoticObjectMode, noValue(), nullptr,
benjamin@webkit.org2e864d22015-11-17 06:20:21 +00003157 m_out.notZero32(m_out.load8ZeroExt32(arguments, m_heaps.ScopedArguments_overrodeThings)));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003158 setInt32(m_out.load32NonNegative(arguments, m_heaps.ScopedArguments_totalLength));
3159 return;
3160 }
3161
oliver@apple.comea771492013-07-25 03:58:38 +00003162 default:
keith_miller@apple.com59bba5d2015-10-16 22:18:42 +00003163 if (m_node->arrayMode().isSomeTypedArrayView()) {
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +00003164 setInt32(
msaboff@apple.com95894332014-01-29 19:18:54 +00003165 m_out.load32NonNegative(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length));
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +00003166 return;
3167 }
3168
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00003169 DFG_CRASH(m_graph, m_node, "Bad array type");
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +00003170 return;
oliver@apple.comea771492013-07-25 03:58:38 +00003171 }
3172 }
3173
fpizlo@apple.com8624c4b2013-12-10 03:24:31 +00003174 void compileCheckInBounds()
3175 {
3176 speculate(
3177 OutOfBounds, noValue(), 0,
3178 m_out.aboveOrEqual(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
3179 }
3180
oliver@apple.comea771492013-07-25 03:58:38 +00003181 void compileGetByVal()
3182 {
oliver@apple.comea771492013-07-25 03:58:38 +00003183 switch (m_node->arrayMode().type()) {
3184 case Array::Int32:
3185 case Array::Contiguous: {
fpizlo@apple.com1d2175a2013-11-06 04:38:23 +00003186 LValue index = lowInt32(m_node->child2());
3187 LValue storage = lowStorage(m_node->child3());
3188
fpizlo@apple.com5dba3f12013-12-06 22:05:10 +00003189 IndexedAbstractHeap& heap = m_node->arrayMode().type() == Array::Int32 ?
3190 m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties;
3191
oliver@apple.comea771492013-07-25 03:58:38 +00003192 if (m_node->arrayMode().isInBounds()) {
fpizlo@apple.com5dba3f12013-12-06 22:05:10 +00003193 LValue result = m_out.load64(baseIndex(heap, storage, index, m_node->child2()));
fpizlo@apple.com661530a2015-05-09 00:18:43 +00003194 LValue isHole = m_out.isZero64(result);
3195 if (m_node->arrayMode().isSaneChain()) {
3196 DFG_ASSERT(
3197 m_graph, m_node, m_node->arrayMode().type() == Array::Contiguous);
3198 result = m_out.select(
3199 isHole, m_out.constInt64(JSValue::encode(jsUndefined())), result);
3200 } else
3201 speculate(LoadFromHole, noValue(), 0, isHole);
oliver@apple.com827d2cf2013-07-25 04:04:45 +00003202 setJSValue(result);
oliver@apple.com5b4f1422013-07-25 04:03:54 +00003203 return;
oliver@apple.comea771492013-07-25 03:58:38 +00003204 }
3205
fpizlo@apple.com5dba3f12013-12-06 22:05:10 +00003206 LValue base = lowCell(m_node->child1());
3207
fpizlo@apple.com91331742016-03-07 02:07:28 +00003208 LBasicBlock fastCase = m_out.newBlock();
3209 LBasicBlock slowCase = m_out.newBlock();
3210 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com5dba3f12013-12-06 22:05:10 +00003211
3212 m_out.branch(
3213 m_out.aboveOrEqual(
msaboff@apple.com95894332014-01-29 19:18:54 +00003214 index, m_out.load32NonNegative(storage, m_heaps.Butterfly_publicLength)),
fpizlo@apple.com975ae502014-02-19 22:29:43 +00003215 rarely(slowCase), usually(fastCase));
fpizlo@apple.com5dba3f12013-12-06 22:05:10 +00003216
3217 LBasicBlock lastNext = m_out.appendTo(fastCase, slowCase);
fpizlo@apple.com373ed6b2015-12-15 04:52:55 +00003218
3219 LValue fastResultValue = m_out.load64(baseIndex(heap, storage, index, m_node->child2()));
3220 ValueFromBlock fastResult = m_out.anchor(fastResultValue);
fpizlo@apple.com975ae502014-02-19 22:29:43 +00003221 m_out.branch(
fpizlo@apple.com373ed6b2015-12-15 04:52:55 +00003222 m_out.isZero64(fastResultValue), rarely(slowCase), usually(continuation));
fpizlo@apple.com5dba3f12013-12-06 22:05:10 +00003223
3224 m_out.appendTo(slowCase, continuation);
3225 ValueFromBlock slowResult = m_out.anchor(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00003226 vmCall(Int64, m_out.operation(operationGetByValArrayInt), m_callFrame, base, index));
fpizlo@apple.com5dba3f12013-12-06 22:05:10 +00003227 m_out.jump(continuation);
3228
3229 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00003230 setJSValue(m_out.phi(Int64, fastResult, slowResult));
oliver@apple.com5b4f1422013-07-25 04:03:54 +00003231 return;
oliver@apple.comea771492013-07-25 03:58:38 +00003232 }
3233
oliver@apple.com32295c12013-07-25 03:59:06 +00003234 case Array::Double: {
fpizlo@apple.com1d2175a2013-11-06 04:38:23 +00003235 LValue index = lowInt32(m_node->child2());
3236 LValue storage = lowStorage(m_node->child3());
3237
fpizlo@apple.com5dba3f12013-12-06 22:05:10 +00003238 IndexedAbstractHeap& heap = m_heaps.indexedDoubleProperties;
3239
oliver@apple.com32295c12013-07-25 03:59:06 +00003240 if (m_node->arrayMode().isInBounds()) {
fpizlo@apple.com5dba3f12013-12-06 22:05:10 +00003241 LValue result = m_out.loadDouble(
3242 baseIndex(heap, storage, index, m_node->child2()));
oliver@apple.com32295c12013-07-25 03:59:06 +00003243
3244 if (!m_node->arrayMode().isSaneChain()) {
3245 speculate(
3246 LoadFromHole, noValue(), 0,
3247 m_out.doubleNotEqualOrUnordered(result, result));
3248 }
oliver@apple.com827d2cf2013-07-25 04:04:45 +00003249 setDouble(result);
oliver@apple.com32295c12013-07-25 03:59:06 +00003250 break;
3251 }
3252
fpizlo@apple.com5dba3f12013-12-06 22:05:10 +00003253 LValue base = lowCell(m_node->child1());
3254
fpizlo@apple.com91331742016-03-07 02:07:28 +00003255 LBasicBlock inBounds = m_out.newBlock();
3256 LBasicBlock boxPath = m_out.newBlock();
3257 LBasicBlock slowCase = m_out.newBlock();
3258 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com5dba3f12013-12-06 22:05:10 +00003259
3260 m_out.branch(
3261 m_out.aboveOrEqual(
msaboff@apple.com95894332014-01-29 19:18:54 +00003262 index, m_out.load32NonNegative(storage, m_heaps.Butterfly_publicLength)),
fpizlo@apple.com975ae502014-02-19 22:29:43 +00003263 rarely(slowCase), usually(inBounds));
fpizlo@apple.com5dba3f12013-12-06 22:05:10 +00003264
3265 LBasicBlock lastNext = m_out.appendTo(inBounds, boxPath);
3266 LValue doubleValue = m_out.loadDouble(
3267 baseIndex(heap, storage, index, m_node->child2()));
3268 m_out.branch(
fpizlo@apple.com975ae502014-02-19 22:29:43 +00003269 m_out.doubleNotEqualOrUnordered(doubleValue, doubleValue),
3270 rarely(slowCase), usually(boxPath));
fpizlo@apple.com5dba3f12013-12-06 22:05:10 +00003271
3272 m_out.appendTo(boxPath, slowCase);
3273 ValueFromBlock fastResult = m_out.anchor(boxDouble(doubleValue));
3274 m_out.jump(continuation);
3275
3276 m_out.appendTo(slowCase, continuation);
3277 ValueFromBlock slowResult = m_out.anchor(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00003278 vmCall(Int64, m_out.operation(operationGetByValArrayInt), m_callFrame, base, index));
fpizlo@apple.com5dba3f12013-12-06 22:05:10 +00003279 m_out.jump(continuation);
3280
3281 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00003282 setJSValue(m_out.phi(Int64, fastResult, slowResult));
oliver@apple.com5b4f1422013-07-25 04:03:54 +00003283 return;
oliver@apple.com32295c12013-07-25 03:59:06 +00003284 }
benjamin@webkit.org5c3fb3a2015-08-14 03:54:32 +00003285
3286 case Array::Undecided: {
3287 LValue index = lowInt32(m_node->child2());
3288
3289 speculate(OutOfBounds, noValue(), m_node, m_out.lessThan(index, m_out.int32Zero));
3290 setJSValue(m_out.constInt64(ValueUndefined));
3291 return;
3292 }
oliver@apple.com32295c12013-07-25 03:59:06 +00003293
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003294 case Array::DirectArguments: {
3295 LValue base = lowCell(m_node->child1());
3296 LValue index = lowInt32(m_node->child2());
3297
3298 speculate(
3299 ExoticObjectMode, noValue(), nullptr,
commit-queue@webkit.org812d82a2016-12-24 21:26:22 +00003300 m_out.notNull(m_out.loadPtr(base, m_heaps.DirectArguments_mappedArguments)));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003301 speculate(
3302 ExoticObjectMode, noValue(), nullptr,
3303 m_out.aboveOrEqual(
3304 index,
3305 m_out.load32NonNegative(base, m_heaps.DirectArguments_length)));
3306
3307 TypedPointer address = m_out.baseIndex(
3308 m_heaps.DirectArguments_storage, base, m_out.zeroExtPtr(index));
3309 setJSValue(m_out.load64(address));
3310 return;
3311 }
3312
3313 case Array::ScopedArguments: {
3314 LValue base = lowCell(m_node->child1());
3315 LValue index = lowInt32(m_node->child2());
3316
3317 speculate(
3318 ExoticObjectMode, noValue(), nullptr,
3319 m_out.aboveOrEqual(
3320 index,
3321 m_out.load32NonNegative(base, m_heaps.ScopedArguments_totalLength)));
3322
3323 LValue table = m_out.loadPtr(base, m_heaps.ScopedArguments_table);
3324 LValue namedLength = m_out.load32(table, m_heaps.ScopedArgumentsTable_length);
3325
fpizlo@apple.com91331742016-03-07 02:07:28 +00003326 LBasicBlock namedCase = m_out.newBlock();
3327 LBasicBlock overflowCase = m_out.newBlock();
3328 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003329
3330 m_out.branch(
3331 m_out.aboveOrEqual(index, namedLength), unsure(overflowCase), unsure(namedCase));
3332
3333 LBasicBlock lastNext = m_out.appendTo(namedCase, overflowCase);
3334
3335 LValue scope = m_out.loadPtr(base, m_heaps.ScopedArguments_scope);
3336 LValue arguments = m_out.loadPtr(table, m_heaps.ScopedArgumentsTable_arguments);
3337
3338 TypedPointer address = m_out.baseIndex(
3339 m_heaps.scopedArgumentsTableArguments, arguments, m_out.zeroExtPtr(index));
3340 LValue scopeOffset = m_out.load32(address);
3341
3342 speculate(
3343 ExoticObjectMode, noValue(), nullptr,
3344 m_out.equal(scopeOffset, m_out.constInt32(ScopeOffset::invalidOffset)));
3345
3346 address = m_out.baseIndex(
3347 m_heaps.JSEnvironmentRecord_variables, scope, m_out.zeroExtPtr(scopeOffset));
3348 ValueFromBlock namedResult = m_out.anchor(m_out.load64(address));
3349 m_out.jump(continuation);
3350
3351 m_out.appendTo(overflowCase, continuation);
3352
3353 address = m_out.baseIndex(
3354 m_heaps.ScopedArguments_overflowStorage, base,
3355 m_out.zeroExtPtr(m_out.sub(index, namedLength)));
3356 LValue overflowValue = m_out.load64(address);
3357 speculate(ExoticObjectMode, noValue(), nullptr, m_out.isZero64(overflowValue));
3358 ValueFromBlock overflowResult = m_out.anchor(overflowValue);
3359 m_out.jump(continuation);
3360
3361 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00003362 setJSValue(m_out.phi(Int64, namedResult, overflowResult));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003363 return;
3364 }
3365
fpizlo@apple.com66421ea2013-12-06 22:54:02 +00003366 case Array::Generic: {
3367 setJSValue(vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00003368 Int64, m_out.operation(operationGetByVal), m_callFrame,
fpizlo@apple.com66421ea2013-12-06 22:54:02 +00003369 lowJSValue(m_node->child1()), lowJSValue(m_node->child2())));
3370 return;
3371 }
3372
fpizlo@apple.com86897bf2013-11-06 02:07:43 +00003373 case Array::String: {
fpizlo@apple.com1d2175a2013-11-06 04:38:23 +00003374 compileStringCharAt();
fpizlo@apple.com86897bf2013-11-06 02:07:43 +00003375 return;
3376 }
3377
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +00003378 default: {
fpizlo@apple.com1d2175a2013-11-06 04:38:23 +00003379 LValue index = lowInt32(m_node->child2());
3380 LValue storage = lowStorage(m_node->child3());
3381
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +00003382 TypedArrayType type = m_node->arrayMode().typedArrayType();
3383
3384 if (isTypedView(type)) {
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +00003385 TypedPointer pointer = TypedPointer(
3386 m_heaps.typedArrayProperties,
3387 m_out.add(
3388 storage,
3389 m_out.shl(
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003390 m_out.zeroExtPtr(index),
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +00003391 m_out.constIntPtr(logElementSize(type)))));
3392
3393 if (isInt(type)) {
3394 LValue result;
3395 switch (elementSize(type)) {
3396 case 1:
benjamin@webkit.org2e864d22015-11-17 06:20:21 +00003397 result = isSigned(type) ? m_out.load8SignExt32(pointer) : m_out.load8ZeroExt32(pointer);
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +00003398 break;
3399 case 2:
benjamin@webkit.org2e864d22015-11-17 06:20:21 +00003400 result = isSigned(type) ? m_out.load16SignExt32(pointer) : m_out.load16ZeroExt32(pointer);
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +00003401 break;
3402 case 4:
3403 result = m_out.load32(pointer);
3404 break;
3405 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00003406 DFG_CRASH(m_graph, m_node, "Bad element size");
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +00003407 }
3408
benjamin@webkit.org2e864d22015-11-17 06:20:21 +00003409 if (elementSize(type) < 4 || isSigned(type)) {
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +00003410 setInt32(result);
3411 return;
3412 }
benjamin@webkit.org2e864d22015-11-17 06:20:21 +00003413
fpizlo@apple.comefacb612013-09-10 22:16:00 +00003414 if (m_node->shouldSpeculateInt32()) {
fpizlo@apple.com84845b42013-12-10 23:36:09 +00003415 speculate(
3416 Overflow, noValue(), 0, m_out.lessThan(result, m_out.int32Zero));
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +00003417 setInt32(result);
3418 return;
3419 }
3420
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00003421 if (m_node->shouldSpeculateAnyInt()) {
fpizlo@apple.com994d4532016-07-03 19:34:55 +00003422 setStrictInt52(m_out.zeroExt(result, Int64));
fpizlo@apple.com1a4f1f22014-03-21 06:51:18 +00003423 return;
3424 }
3425
benjamin@webkit.orge962d972015-12-11 17:15:58 +00003426 setDouble(m_out.unsignedToDouble(result));
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +00003427 return;
3428 }
3429
3430 ASSERT(isFloat(type));
3431
3432 LValue result;
3433 switch (type) {
3434 case TypeFloat32:
benjamin@webkit.orge962d972015-12-11 17:15:58 +00003435 result = m_out.floatToDouble(m_out.loadFloat(pointer));
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +00003436 break;
3437 case TypeFloat64:
3438 result = m_out.loadDouble(pointer);
3439 break;
3440 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00003441 DFG_CRASH(m_graph, m_node, "Bad typed array type");
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +00003442 }
3443
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +00003444 setDouble(result);
3445 return;
3446 }
3447
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00003448 DFG_CRASH(m_graph, m_node, "Bad array type");
oliver@apple.com5b4f1422013-07-25 04:03:54 +00003449 return;
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +00003450 } }
oliver@apple.com5b4f1422013-07-25 04:03:54 +00003451 }
fpizlo@apple.com710c29e2014-02-15 19:45:54 +00003452
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003453 void compileGetMyArgumentByVal()
3454 {
3455 InlineCallFrame* inlineCallFrame = m_node->child1()->origin.semantic.inlineCallFrame;
3456
3457 LValue index = lowInt32(m_node->child2());
sbarati@apple.com7a74ce72016-11-01 20:03:03 +00003458 if (m_node->numberOfArgumentsToSkip())
3459 index = m_out.add(index, m_out.constInt32(m_node->numberOfArgumentsToSkip()));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003460
3461 LValue limit;
3462 if (inlineCallFrame && !inlineCallFrame->isVarargs())
3463 limit = m_out.constInt32(inlineCallFrame->arguments.size() - 1);
3464 else {
utatane.tea@gmail.combebf7852016-11-10 06:34:05 +00003465 VirtualRegister argumentCountRegister = AssemblyHelpers::argumentCount(inlineCallFrame);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003466 limit = m_out.sub(m_out.load32(payloadFor(argumentCountRegister)), m_out.int32One);
3467 }
3468
fpizlo@apple.comc2b8c092016-04-24 17:05:51 +00003469 LValue isOutOfBounds = m_out.aboveOrEqual(index, limit);
3470 LBasicBlock continuation = nullptr;
3471 LBasicBlock lastNext = nullptr;
3472 ValueFromBlock slowResult;
3473 if (m_node->op() == GetMyArgumentByValOutOfBounds) {
3474 LBasicBlock normalCase = m_out.newBlock();
3475 continuation = m_out.newBlock();
3476
3477 slowResult = m_out.anchor(m_out.constInt64(JSValue::encode(jsUndefined())));
3478 m_out.branch(isOutOfBounds, unsure(continuation), unsure(normalCase));
3479
3480 lastNext = m_out.appendTo(normalCase, continuation);
3481 } else
3482 speculate(ExoticObjectMode, noValue(), 0, isOutOfBounds);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003483
3484 TypedPointer base;
3485 if (inlineCallFrame) {
fpizlo@apple.comc2b8c092016-04-24 17:05:51 +00003486 if (inlineCallFrame->arguments.size() > 1)
3487 base = addressFor(inlineCallFrame->arguments[1].virtualRegister());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003488 } else
3489 base = addressFor(virtualRegisterForArgument(1));
3490
fpizlo@apple.comc2b8c092016-04-24 17:05:51 +00003491 LValue result;
3492 if (base) {
3493 LValue pointer = m_out.baseIndex(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00003494 base.value(), m_out.zeroExt(index, pointerType()), ScaleEight);
fpizlo@apple.comc2b8c092016-04-24 17:05:51 +00003495 result = m_out.load64(TypedPointer(m_heaps.variables.atAnyIndex(), pointer));
3496 } else
3497 result = m_out.constInt64(JSValue::encode(jsUndefined()));
3498
3499 if (m_node->op() == GetMyArgumentByValOutOfBounds) {
3500 ValueFromBlock normalResult = m_out.anchor(result);
3501 m_out.jump(continuation);
3502
3503 m_out.appendTo(continuation, lastNext);
3504 result = m_out.phi(Int64, slowResult, normalResult);
3505 }
3506
3507 setJSValue(result);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003508 }
3509
oliver@apple.com5b4f1422013-07-25 04:03:54 +00003510 void compilePutByVal()
3511 {
3512 Edge child1 = m_graph.varArgChild(m_node, 0);
3513 Edge child2 = m_graph.varArgChild(m_node, 1);
3514 Edge child3 = m_graph.varArgChild(m_node, 2);
3515 Edge child4 = m_graph.varArgChild(m_node, 3);
msaboff@apple.com95894332014-01-29 19:18:54 +00003516 Edge child5 = m_graph.varArgChild(m_node, 4);
fpizlo@apple.com66421ea2013-12-06 22:54:02 +00003517
3518 switch (m_node->arrayMode().type()) {
3519 case Array::Generic: {
3520 V_JITOperation_EJJJ operation;
3521 if (m_node->op() == PutByValDirect) {
fpizlo@apple.com6793a322014-02-12 05:42:32 +00003522 if (m_graph.isStrictModeFor(m_node->origin.semantic))
fpizlo@apple.com66421ea2013-12-06 22:54:02 +00003523 operation = operationPutByValDirectStrict;
3524 else
3525 operation = operationPutByValDirectNonStrict;
3526 } else {
fpizlo@apple.com6793a322014-02-12 05:42:32 +00003527 if (m_graph.isStrictModeFor(m_node->origin.semantic))
fpizlo@apple.com66421ea2013-12-06 22:54:02 +00003528 operation = operationPutByValStrict;
3529 else
3530 operation = operationPutByValNonStrict;
3531 }
3532
3533 vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00003534 Void, m_out.operation(operation), m_callFrame,
fpizlo@apple.com66421ea2013-12-06 22:54:02 +00003535 lowJSValue(child1), lowJSValue(child2), lowJSValue(child3));
3536 return;
3537 }
3538
3539 default:
3540 break;
3541 }
oliver@apple.com5b4f1422013-07-25 04:03:54 +00003542
oliver@apple.com8c55ed02013-07-25 04:04:01 +00003543 LValue base = lowCell(child1);
oliver@apple.com5b4f1422013-07-25 04:03:54 +00003544 LValue index = lowInt32(child2);
3545 LValue storage = lowStorage(child4);
3546
3547 switch (m_node->arrayMode().type()) {
3548 case Array::Int32:
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003549 case Array::Double:
oliver@apple.com5b4f1422013-07-25 04:03:54 +00003550 case Array::Contiguous: {
fpizlo@apple.com91331742016-03-07 02:07:28 +00003551 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003552 LBasicBlock outerLastNext = m_out.appendTo(m_out.m_block, continuation);
oliver@apple.com5b4f1422013-07-25 04:03:54 +00003553
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003554 switch (m_node->arrayMode().type()) {
3555 case Array::Int32:
3556 case Array::Contiguous: {
3557 LValue value = lowJSValue(child3, ManualOperandSpeculation);
3558
3559 if (m_node->arrayMode().type() == Array::Int32)
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00003560 FTL_TYPE_CHECK(jsValueValue(value), child3, SpecInt32Only, isNotInt32(value));
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003561
3562 TypedPointer elementPointer = m_out.baseIndex(
3563 m_node->arrayMode().type() == Array::Int32 ?
3564 m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties,
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00003565 storage, m_out.zeroExtPtr(index), provenValue(child2));
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003566
3567 if (m_node->op() == PutByValAlias) {
3568 m_out.store64(value, elementPointer);
3569 break;
3570 }
3571
3572 contiguousPutByValOutOfBounds(
3573 codeBlock()->isStrictMode()
3574 ? operationPutByValBeyondArrayBoundsStrict
3575 : operationPutByValBeyondArrayBoundsNonStrict,
3576 base, storage, index, value, continuation);
3577
oliver@apple.com5b4f1422013-07-25 04:03:54 +00003578 m_out.store64(value, elementPointer);
oliver@apple.com8c55ed02013-07-25 04:04:01 +00003579 break;
oliver@apple.com5b4f1422013-07-25 04:03:54 +00003580 }
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003581
3582 case Array::Double: {
3583 LValue value = lowDouble(child3);
3584
3585 FTL_TYPE_CHECK(
fpizlo@apple.combeef4522014-04-16 22:44:00 +00003586 doubleValue(value), child3, SpecDoubleReal,
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003587 m_out.doubleNotEqualOrUnordered(value, value));
3588
3589 TypedPointer elementPointer = m_out.baseIndex(
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003590 m_heaps.indexedDoubleProperties, storage, m_out.zeroExtPtr(index),
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00003591 provenValue(child2));
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003592
3593 if (m_node->op() == PutByValAlias) {
3594 m_out.storeDouble(value, elementPointer);
3595 break;
3596 }
3597
3598 contiguousPutByValOutOfBounds(
3599 codeBlock()->isStrictMode()
3600 ? operationPutDoubleByValBeyondArrayBoundsStrict
3601 : operationPutDoubleByValBeyondArrayBoundsNonStrict,
3602 base, storage, index, value, continuation);
3603
oliver@apple.com5b4f1422013-07-25 04:03:54 +00003604 m_out.storeDouble(value, elementPointer);
oliver@apple.com8c55ed02013-07-25 04:04:01 +00003605 break;
oliver@apple.com5b4f1422013-07-25 04:03:54 +00003606 }
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00003607
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003608 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00003609 DFG_CRASH(m_graph, m_node, "Bad array type");
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003610 }
3611
3612 m_out.jump(continuation);
3613 m_out.appendTo(continuation, outerLastNext);
3614 return;
oliver@apple.com5b4f1422013-07-25 04:03:54 +00003615 }
3616
3617 default:
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003618 TypedArrayType type = m_node->arrayMode().typedArrayType();
3619
3620 if (isTypedView(type)) {
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003621 TypedPointer pointer = TypedPointer(
3622 m_heaps.typedArrayProperties,
3623 m_out.add(
3624 storage,
3625 m_out.shl(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00003626 m_out.zeroExt(index, pointerType()),
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003627 m_out.constIntPtr(logElementSize(type)))));
3628
fpizlo@apple.comffa67502015-12-11 04:03:28 +00003629 Output::StoreType storeType;
msaboff@apple.com95894332014-01-29 19:18:54 +00003630 LValue valueToStore;
3631
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003632 if (isInt(type)) {
3633 LValue intValue;
3634 switch (child3.useKind()) {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00003635 case Int52RepUse:
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003636 case Int32Use: {
commit-queue@webkit.org450fbd12013-10-16 03:59:12 +00003637 if (child3.useKind() == Int32Use)
3638 intValue = lowInt32(child3);
3639 else
fpizlo@apple.com6f2bf6c2013-12-06 20:59:16 +00003640 intValue = m_out.castToInt32(lowStrictInt52(child3));
commit-queue@webkit.org450fbd12013-10-16 03:59:12 +00003641
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003642 if (isClamped(type)) {
3643 ASSERT(elementSize(type) == 1);
3644
fpizlo@apple.com91331742016-03-07 02:07:28 +00003645 LBasicBlock atLeastZero = m_out.newBlock();
3646 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003647
3648 Vector<ValueFromBlock, 2> intValues;
3649 intValues.append(m_out.anchor(m_out.int32Zero));
3650 m_out.branch(
3651 m_out.lessThan(intValue, m_out.int32Zero),
fpizlo@apple.com975ae502014-02-19 22:29:43 +00003652 unsure(continuation), unsure(atLeastZero));
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003653
3654 LBasicBlock lastNext = m_out.appendTo(atLeastZero, continuation);
3655
3656 intValues.append(m_out.anchor(m_out.select(
3657 m_out.greaterThan(intValue, m_out.constInt32(255)),
3658 m_out.constInt32(255),
3659 intValue)));
3660 m_out.jump(continuation);
3661
3662 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00003663 intValue = m_out.phi(Int32, intValues);
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003664 }
3665 break;
3666 }
3667
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00003668 case DoubleRepUse: {
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003669 LValue doubleValue = lowDouble(child3);
3670
3671 if (isClamped(type)) {
3672 ASSERT(elementSize(type) == 1);
3673
fpizlo@apple.com91331742016-03-07 02:07:28 +00003674 LBasicBlock atLeastZero = m_out.newBlock();
3675 LBasicBlock withinRange = m_out.newBlock();
3676 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003677
3678 Vector<ValueFromBlock, 3> intValues;
3679 intValues.append(m_out.anchor(m_out.int32Zero));
3680 m_out.branch(
3681 m_out.doubleLessThanOrUnordered(doubleValue, m_out.doubleZero),
fpizlo@apple.com975ae502014-02-19 22:29:43 +00003682 unsure(continuation), unsure(atLeastZero));
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003683
3684 LBasicBlock lastNext = m_out.appendTo(atLeastZero, withinRange);
3685 intValues.append(m_out.anchor(m_out.constInt32(255)));
3686 m_out.branch(
3687 m_out.doubleGreaterThan(doubleValue, m_out.constDouble(255)),
fpizlo@apple.com975ae502014-02-19 22:29:43 +00003688 unsure(continuation), unsure(withinRange));
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003689
3690 m_out.appendTo(withinRange, continuation);
fpizlo@apple.comdae23fb2015-12-21 20:54:51 +00003691 intValues.append(m_out.anchor(m_out.doubleToInt(doubleValue)));
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003692 m_out.jump(continuation);
3693
3694 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00003695 intValue = m_out.phi(Int32, intValues);
fpizlo@apple.coma498a262013-12-06 20:30:31 +00003696 } else
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003697 intValue = doubleToInt32(doubleValue);
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003698 break;
3699 }
3700
3701 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00003702 DFG_CRASH(m_graph, m_node, "Bad use kind");
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003703 }
fpizlo@apple.comffa67502015-12-11 04:03:28 +00003704
3705 valueToStore = intValue;
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003706 switch (elementSize(type)) {
3707 case 1:
fpizlo@apple.comffa67502015-12-11 04:03:28 +00003708 storeType = Output::Store32As8;
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003709 break;
3710 case 2:
fpizlo@apple.comffa67502015-12-11 04:03:28 +00003711 storeType = Output::Store32As16;
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003712 break;
3713 case 4:
fpizlo@apple.comffa67502015-12-11 04:03:28 +00003714 storeType = Output::Store32;
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003715 break;
3716 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00003717 DFG_CRASH(m_graph, m_node, "Bad element size");
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003718 }
msaboff@apple.com95894332014-01-29 19:18:54 +00003719 } else /* !isInt(type) */ {
3720 LValue value = lowDouble(child3);
3721 switch (type) {
3722 case TypeFloat32:
benjamin@webkit.orge962d972015-12-11 17:15:58 +00003723 valueToStore = m_out.doubleToFloat(value);
fpizlo@apple.comffa67502015-12-11 04:03:28 +00003724 storeType = Output::StoreFloat;
msaboff@apple.com95894332014-01-29 19:18:54 +00003725 break;
3726 case TypeFloat64:
3727 valueToStore = value;
fpizlo@apple.comffa67502015-12-11 04:03:28 +00003728 storeType = Output::StoreDouble;
msaboff@apple.com95894332014-01-29 19:18:54 +00003729 break;
3730 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00003731 DFG_CRASH(m_graph, m_node, "Bad typed array type");
msaboff@apple.com95894332014-01-29 19:18:54 +00003732 }
3733 }
keith_miller@apple.com723825f2016-07-08 16:27:35 +00003734
fpizlo@apple.com836099a2014-02-05 01:03:21 +00003735 if (m_node->arrayMode().isInBounds() || m_node->op() == PutByValAlias)
fpizlo@apple.comffa67502015-12-11 04:03:28 +00003736 m_out.store(valueToStore, pointer, storeType);
msaboff@apple.com95894332014-01-29 19:18:54 +00003737 else {
fpizlo@apple.com91331742016-03-07 02:07:28 +00003738 LBasicBlock isInBounds = m_out.newBlock();
keith_miller@apple.com723825f2016-07-08 16:27:35 +00003739 LBasicBlock isOutOfBounds = m_out.newBlock();
fpizlo@apple.com91331742016-03-07 02:07:28 +00003740 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003741
msaboff@apple.com95894332014-01-29 19:18:54 +00003742 m_out.branch(
3743 m_out.aboveOrEqual(index, lowInt32(child5)),
keith_miller@apple.com723825f2016-07-08 16:27:35 +00003744 unsure(isOutOfBounds), unsure(isInBounds));
msaboff@apple.com95894332014-01-29 19:18:54 +00003745
keith_miller@apple.com723825f2016-07-08 16:27:35 +00003746 LBasicBlock lastNext = m_out.appendTo(isInBounds, isOutOfBounds);
fpizlo@apple.comffa67502015-12-11 04:03:28 +00003747 m_out.store(valueToStore, pointer, storeType);
msaboff@apple.com95894332014-01-29 19:18:54 +00003748 m_out.jump(continuation);
keith_miller@apple.com723825f2016-07-08 16:27:35 +00003749
3750 m_out.appendTo(isOutOfBounds, continuation);
3751 speculateTypedArrayIsNotNeutered(base);
3752 m_out.jump(continuation);
msaboff@apple.com95894332014-01-29 19:18:54 +00003753
3754 m_out.appendTo(continuation, lastNext);
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003755 }
3756
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +00003757 return;
3758 }
keith_miller@apple.com723825f2016-07-08 16:27:35 +00003759
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00003760 DFG_CRASH(m_graph, m_node, "Bad array type");
3761 break;
oliver@apple.comea771492013-07-25 03:58:38 +00003762 }
3763 }
utatane.tea@gmail.com287d64c2015-10-27 07:00:57 +00003764
3765 void compilePutAccessorById()
3766 {
3767 LValue base = lowCell(m_node->child1());
3768 LValue accessor = lowCell(m_node->child2());
3769 auto uid = m_graph.identifiers()[m_node->identifierNumber()];
3770 vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00003771 Void,
utatane.tea@gmail.com287d64c2015-10-27 07:00:57 +00003772 m_out.operation(m_node->op() == PutGetterById ? operationPutGetterById : operationPutSetterById),
3773 m_callFrame, base, m_out.constIntPtr(uid), m_out.constInt32(m_node->accessorAttributes()), accessor);
3774 }
3775
3776 void compilePutGetterSetterById()
3777 {
3778 LValue base = lowCell(m_node->child1());
3779 LValue getter = lowJSValue(m_node->child2());
3780 LValue setter = lowJSValue(m_node->child3());
3781 auto uid = m_graph.identifiers()[m_node->identifierNumber()];
3782 vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00003783 Void, m_out.operation(operationPutGetterSetter),
utatane.tea@gmail.com287d64c2015-10-27 07:00:57 +00003784 m_callFrame, base, m_out.constIntPtr(uid), m_out.constInt32(m_node->accessorAttributes()), getter, setter);
3785
3786 }
3787
3788 void compilePutAccessorByVal()
3789 {
3790 LValue base = lowCell(m_node->child1());
3791 LValue subscript = lowJSValue(m_node->child2());
3792 LValue accessor = lowCell(m_node->child3());
3793 vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00003794 Void,
utatane.tea@gmail.com287d64c2015-10-27 07:00:57 +00003795 m_out.operation(m_node->op() == PutGetterByVal ? operationPutGetterByVal : operationPutSetterByVal),
3796 m_callFrame, base, subscript, m_out.constInt32(m_node->accessorAttributes()), accessor);
3797 }
oliver@apple.comea771492013-07-25 03:58:38 +00003798
fpizlo@apple.com85ab8b52014-01-30 07:30:24 +00003799 void compileArrayPush()
3800 {
3801 LValue base = lowCell(m_node->child1());
3802 LValue storage = lowStorage(m_node->child3());
3803
3804 switch (m_node->arrayMode().type()) {
3805 case Array::Int32:
3806 case Array::Contiguous:
3807 case Array::Double: {
3808 LValue value;
fpizlo@apple.comffa67502015-12-11 04:03:28 +00003809 Output::StoreType storeType;
fpizlo@apple.com85ab8b52014-01-30 07:30:24 +00003810
3811 if (m_node->arrayMode().type() != Array::Double) {
3812 value = lowJSValue(m_node->child2(), ManualOperandSpeculation);
3813 if (m_node->arrayMode().type() == Array::Int32) {
3814 FTL_TYPE_CHECK(
mark.lam@apple.com39e9c982016-04-25 17:48:46 +00003815 jsValueValue(value), m_node->child2(), SpecInt32Only, isNotInt32(value));
fpizlo@apple.com85ab8b52014-01-30 07:30:24 +00003816 }
fpizlo@apple.comffa67502015-12-11 04:03:28 +00003817 storeType = Output::Store64;
fpizlo@apple.com85ab8b52014-01-30 07:30:24 +00003818 } else {
3819 value = lowDouble(m_node->child2());
3820 FTL_TYPE_CHECK(
fpizlo@apple.combeef4522014-04-16 22:44:00 +00003821 doubleValue(value), m_node->child2(), SpecDoubleReal,
fpizlo@apple.com85ab8b52014-01-30 07:30:24 +00003822 m_out.doubleNotEqualOrUnordered(value, value));
fpizlo@apple.comffa67502015-12-11 04:03:28 +00003823 storeType = Output::StoreDouble;
fpizlo@apple.com85ab8b52014-01-30 07:30:24 +00003824 }
3825
3826 IndexedAbstractHeap& heap = m_heaps.forArrayType(m_node->arrayMode().type());
3827
3828 LValue prevLength = m_out.load32(storage, m_heaps.Butterfly_publicLength);
3829
fpizlo@apple.com91331742016-03-07 02:07:28 +00003830 LBasicBlock fastPath = m_out.newBlock();
3831 LBasicBlock slowPath = m_out.newBlock();
3832 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com85ab8b52014-01-30 07:30:24 +00003833
3834 m_out.branch(
3835 m_out.aboveOrEqual(
3836 prevLength, m_out.load32(storage, m_heaps.Butterfly_vectorLength)),
fpizlo@apple.com28c71002016-01-15 19:41:56 +00003837 unsure(slowPath), unsure(fastPath));
fpizlo@apple.com85ab8b52014-01-30 07:30:24 +00003838
3839 LBasicBlock lastNext = m_out.appendTo(fastPath, slowPath);
3840 m_out.store(
fpizlo@apple.comffa67502015-12-11 04:03:28 +00003841 value, m_out.baseIndex(heap, storage, m_out.zeroExtPtr(prevLength)), storeType);
fpizlo@apple.com85ab8b52014-01-30 07:30:24 +00003842 LValue newLength = m_out.add(prevLength, m_out.int32One);
3843 m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength);
3844
3845 ValueFromBlock fastResult = m_out.anchor(boxInt32(newLength));
3846 m_out.jump(continuation);
3847
3848 m_out.appendTo(slowPath, continuation);
3849 LValue operation;
3850 if (m_node->arrayMode().type() != Array::Double)
3851 operation = m_out.operation(operationArrayPush);
3852 else
3853 operation = m_out.operation(operationArrayPushDouble);
3854 ValueFromBlock slowResult = m_out.anchor(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00003855 vmCall(Int64, operation, m_callFrame, value, base));
fpizlo@apple.com85ab8b52014-01-30 07:30:24 +00003856 m_out.jump(continuation);
3857
3858 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00003859 setJSValue(m_out.phi(Int64, fastResult, slowResult));
fpizlo@apple.com85ab8b52014-01-30 07:30:24 +00003860 return;
3861 }
3862
3863 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00003864 DFG_CRASH(m_graph, m_node, "Bad array type");
fpizlo@apple.com85ab8b52014-01-30 07:30:24 +00003865 return;
3866 }
3867 }
sbarati@apple.comfd407a52017-01-13 04:03:47 +00003868
3869 void compileArraySlice()
3870 {
3871 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
3872
3873 LValue sourceStorage = lowStorage(m_node->numChildren() == 3 ? m_graph.varArgChild(m_node, 2) : m_graph.varArgChild(m_node, 3));
3874 LValue inputLength = m_out.load32(sourceStorage, m_heaps.Butterfly_publicLength);
3875
3876 LValue endBoundary;
3877 if (m_node->numChildren() == 3)
3878 endBoundary = m_out.load32(sourceStorage, m_heaps.Butterfly_publicLength);
3879 else {
3880 endBoundary = lowInt32(m_graph.varArgChild(m_node, 2));
3881 endBoundary = m_out.select(m_out.greaterThanOrEqual(endBoundary, m_out.constInt32(0)),
3882 m_out.select(m_out.above(endBoundary, inputLength), inputLength, endBoundary),
3883 m_out.select(m_out.lessThan(m_out.add(inputLength, endBoundary), m_out.constInt32(0)), m_out.constInt32(0), m_out.add(inputLength, endBoundary)));
3884 }
3885
3886 LValue startIndex = lowInt32(m_graph.varArgChild(m_node, 1));
3887 startIndex = m_out.select(m_out.greaterThanOrEqual(startIndex, m_out.constInt32(0)),
3888 m_out.select(m_out.above(startIndex, inputLength), inputLength, startIndex),
3889 m_out.select(m_out.lessThan(m_out.add(inputLength, startIndex), m_out.constInt32(0)), m_out.constInt32(0), m_out.add(inputLength, startIndex)));
3890
3891 LValue resultLength = m_out.select(m_out.below(startIndex, endBoundary),
3892 m_out.sub(endBoundary, startIndex),
3893 m_out.constInt32(0));
3894
3895 ArrayValues arrayResult;
3896 {
3897 LValue indexingType = m_out.load8ZeroExt32(lowCell(m_graph.varArgChild(m_node, 0)), m_heaps.JSCell_indexingTypeAndMisc);
3898 indexingType = m_out.bitAnd(indexingType, m_out.constInt32(AllArrayTypesAndHistory));
3899 // When we emit an ArraySlice, we dominate the use of the array by a CheckStructure
3900 // to ensure the incoming array is one to be one of the original array structures
3901 // with one of the following indexing shapes: Int32, Contiguous, Double.
3902 LValue structure = m_out.select(
3903 m_out.equal(indexingType, m_out.constInt32(ArrayWithInt32)),
sbarati@apple.com239d20b2017-01-26 23:50:58 +00003904 weakStructure(m_graph.registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithInt32))),
sbarati@apple.comfd407a52017-01-13 04:03:47 +00003905 m_out.select(m_out.equal(indexingType, m_out.constInt32(ArrayWithContiguous)),
sbarati@apple.com239d20b2017-01-26 23:50:58 +00003906 weakStructure(m_graph.registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous))),
3907 weakStructure(m_graph.registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithDouble)))));
sbarati@apple.comfd407a52017-01-13 04:03:47 +00003908 arrayResult = allocateJSArray(resultLength, structure, indexingType, false, false);
3909 }
3910
3911 LBasicBlock loop = m_out.newBlock();
3912 LBasicBlock continuation = m_out.newBlock();
3913
3914 resultLength = m_out.zeroExtPtr(resultLength);
3915 ValueFromBlock startLoadIndex = m_out.anchor(m_out.zeroExtPtr(startIndex));
3916 ValueFromBlock startStoreIndex = m_out.anchor(m_out.constIntPtr(0));
3917
3918 m_out.branch(
3919 m_out.below(m_out.constIntPtr(0), resultLength), unsure(loop), unsure(continuation));
3920
3921 LBasicBlock lastNext = m_out.appendTo(loop, continuation);
3922 LValue storeIndex = m_out.phi(pointerType(), startStoreIndex);
3923 LValue loadIndex = m_out.phi(pointerType(), startLoadIndex);
3924 LValue value = m_out.load64(m_out.baseIndex(m_heaps.root, sourceStorage, loadIndex, ScaleEight));
3925 m_out.store64(value, m_out.baseIndex(m_heaps.root, arrayResult.butterfly, storeIndex, ScaleEight));
3926 LValue nextStoreIndex = m_out.add(storeIndex, m_out.constIntPtr(1));
3927 m_out.addIncomingToPhi(storeIndex, m_out.anchor(nextStoreIndex));
3928 m_out.addIncomingToPhi(loadIndex, m_out.anchor(m_out.add(loadIndex, m_out.constIntPtr(1))));
3929 m_out.branch(
3930 m_out.below(nextStoreIndex, resultLength), unsure(loop), unsure(continuation));
3931
3932 m_out.appendTo(continuation, lastNext);
3933
3934 mutatorFence();
3935 setJSValue(arrayResult.array);
3936 }
fpizlo@apple.com85ab8b52014-01-30 07:30:24 +00003937
3938 void compileArrayPop()
3939 {
3940 LValue base = lowCell(m_node->child1());
3941 LValue storage = lowStorage(m_node->child2());
3942
3943 switch (m_node->arrayMode().type()) {
3944 case Array::Int32:
3945 case Array::Double:
3946 case Array::Contiguous: {
3947 IndexedAbstractHeap& heap = m_heaps.forArrayType(m_node->arrayMode().type());
3948
fpizlo@apple.com91331742016-03-07 02:07:28 +00003949 LBasicBlock fastCase = m_out.newBlock();
3950 LBasicBlock slowCase = m_out.newBlock();
3951 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com85ab8b52014-01-30 07:30:24 +00003952
3953 LValue prevLength = m_out.load32(storage, m_heaps.Butterfly_publicLength);
3954
3955 Vector<ValueFromBlock, 3> results;
3956 results.append(m_out.anchor(m_out.constInt64(JSValue::encode(jsUndefined()))));
fpizlo@apple.com975ae502014-02-19 22:29:43 +00003957 m_out.branch(
3958 m_out.isZero32(prevLength), rarely(continuation), usually(fastCase));
fpizlo@apple.com85ab8b52014-01-30 07:30:24 +00003959
3960 LBasicBlock lastNext = m_out.appendTo(fastCase, slowCase);
3961 LValue newLength = m_out.sub(prevLength, m_out.int32One);
3962 m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003963 TypedPointer pointer = m_out.baseIndex(heap, storage, m_out.zeroExtPtr(newLength));
fpizlo@apple.com85ab8b52014-01-30 07:30:24 +00003964 if (m_node->arrayMode().type() != Array::Double) {
3965 LValue result = m_out.load64(pointer);
3966 m_out.store64(m_out.int64Zero, pointer);
3967 results.append(m_out.anchor(result));
fpizlo@apple.com975ae502014-02-19 22:29:43 +00003968 m_out.branch(
3969 m_out.notZero64(result), usually(continuation), rarely(slowCase));
fpizlo@apple.com85ab8b52014-01-30 07:30:24 +00003970 } else {
3971 LValue result = m_out.loadDouble(pointer);
fpizlo@apple.combeef4522014-04-16 22:44:00 +00003972 m_out.store64(m_out.constInt64(bitwise_cast<int64_t>(PNaN)), pointer);
fpizlo@apple.com85ab8b52014-01-30 07:30:24 +00003973 results.append(m_out.anchor(boxDouble(result)));
fpizlo@apple.com975ae502014-02-19 22:29:43 +00003974 m_out.branch(
3975 m_out.doubleEqual(result, result),
3976 usually(continuation), rarely(slowCase));
fpizlo@apple.com85ab8b52014-01-30 07:30:24 +00003977 }
3978
3979 m_out.appendTo(slowCase, continuation);
3980 results.append(m_out.anchor(vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00003981 Int64, m_out.operation(operationArrayPopAndRecoverLength), m_callFrame, base)));
fpizlo@apple.com85ab8b52014-01-30 07:30:24 +00003982 m_out.jump(continuation);
3983
3984 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00003985 setJSValue(m_out.phi(Int64, results));
fpizlo@apple.com85ab8b52014-01-30 07:30:24 +00003986 return;
3987 }
3988
3989 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00003990 DFG_CRASH(m_graph, m_node, "Bad array type");
fpizlo@apple.com85ab8b52014-01-30 07:30:24 +00003991 return;
3992 }
3993 }
3994
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003995 void compileCreateActivation()
3996 {
3997 LValue scope = lowCell(m_node->child1());
saambarati1@gmail.com402b5852015-05-22 02:39:25 +00003998 SymbolTable* table = m_node->castOperand<SymbolTable*>();
sbarati@apple.com239d20b2017-01-26 23:50:58 +00003999 RegisteredStructure structure = m_graph.registerStructure(m_graph.globalObjectFor(m_node->origin.semantic)->activationStructure());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00004000 JSValue initializationValue = m_node->initializationValueForActivation();
4001 ASSERT(initializationValue.isUndefined() || initializationValue == jsTDZValue());
fpizlo@apple.com3a2fa4c2015-04-13 22:13:12 +00004002 if (table->singletonScope()->isStillValid()) {
4003 LValue callResult = vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00004004 Int64,
sbarati@apple.com239d20b2017-01-26 23:50:58 +00004005 m_out.operation(operationCreateActivationDirect), m_callFrame, weakStructure(structure),
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00004006 scope, weakPointer(table), m_out.constInt64(JSValue::encode(initializationValue)));
fpizlo@apple.com3a2fa4c2015-04-13 22:13:12 +00004007 setJSValue(callResult);
4008 return;
4009 }
4010
fpizlo@apple.com91331742016-03-07 02:07:28 +00004011 LBasicBlock slowPath = m_out.newBlock();
4012 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004013
4014 LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
4015
4016 LValue fastObject = allocateObject<JSLexicalEnvironment>(
4017 JSLexicalEnvironment::allocationSize(table), structure, m_out.intPtrZero, slowPath);
4018
4019 // We don't need memory barriers since we just fast-created the activation, so the
4020 // activation must be young.
4021 m_out.storePtr(scope, fastObject, m_heaps.JSScope_next);
4022 m_out.storePtr(weakPointer(table), fastObject, m_heaps.JSSymbolTableObject_symbolTable);
4023
4024 for (unsigned i = 0; i < table->scopeSize(); ++i) {
4025 m_out.store64(
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00004026 m_out.constInt64(JSValue::encode(initializationValue)),
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004027 fastObject, m_heaps.JSEnvironmentRecord_variables[i]);
4028 }
4029
fpizlo@apple.com101a1682016-11-15 01:49:22 +00004030 mutatorFence();
4031
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004032 ValueFromBlock fastResult = m_out.anchor(fastObject);
4033 m_out.jump(continuation);
4034
4035 m_out.appendTo(slowPath, continuation);
fpizlo@apple.com6e697962015-10-12 17:56:26 +00004036 LValue callResult = lazySlowPath(
4037 [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
4038 return createLazyCallGenerator(
4039 operationCreateActivationDirect, locations[0].directGPR(),
sbarati@apple.com239d20b2017-01-26 23:50:58 +00004040 CCallHelpers::TrustedImmPtr(structure.get()), locations[1].directGPR(),
fpizlo@apple.com6e697962015-10-12 17:56:26 +00004041 CCallHelpers::TrustedImmPtr(table),
4042 CCallHelpers::TrustedImm64(JSValue::encode(initializationValue)));
4043 },
4044 scope);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004045 ValueFromBlock slowResult = m_out.anchor(callResult);
4046 m_out.jump(continuation);
4047
4048 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00004049 setJSValue(m_out.phi(pointerType(), fastResult, slowResult));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004050 }
4051
4052 void compileNewFunction()
4053 {
caitp@igalia.com8bc562d2016-11-14 21:14:15 +00004054 ASSERT(m_node->op() == NewFunction || m_node->op() == NewGeneratorFunction || m_node->op() == NewAsyncFunction);
utatane.tea@gmail.com9d9fd322015-12-17 10:33:08 +00004055 bool isGeneratorFunction = m_node->op() == NewGeneratorFunction;
caitp@igalia.com8bc562d2016-11-14 21:14:15 +00004056 bool isAsyncFunction = m_node->op() == NewAsyncFunction;
commit-queue@webkit.orga4201b02015-08-17 22:24:20 +00004057
commit-queue@webkit.org14aa0542015-04-17 00:44:58 +00004058 LValue scope = lowCell(m_node->child1());
commit-queue@webkit.orga4201b02015-08-17 22:24:20 +00004059
fpizlo@apple.com3a2fa4c2015-04-13 22:13:12 +00004060 FunctionExecutable* executable = m_node->castOperand<FunctionExecutable*>();
commit-queue@webkit.org14aa0542015-04-17 00:44:58 +00004061 if (executable->singletonFunction()->isStillValid()) {
utatane.tea@gmail.com9d9fd322015-12-17 10:33:08 +00004062 LValue callResult =
fpizlo@apple.com994d4532016-07-03 19:34:55 +00004063 isGeneratorFunction ? vmCall(Int64, m_out.operation(operationNewGeneratorFunction), m_callFrame, scope, weakPointer(executable)) :
caitp@igalia.com8bc562d2016-11-14 21:14:15 +00004064 isAsyncFunction ? vmCall(Int64, m_out.operation(operationNewAsyncFunction), m_callFrame, scope, weakPointer(executable)) :
fpizlo@apple.com994d4532016-07-03 19:34:55 +00004065 vmCall(Int64, m_out.operation(operationNewFunction), m_callFrame, scope, weakPointer(executable));
commit-queue@webkit.org14aa0542015-04-17 00:44:58 +00004066 setJSValue(callResult);
4067 return;
4068 }
fpizlo@apple.com3a2fa4c2015-04-13 22:13:12 +00004069
sbarati@apple.com239d20b2017-01-26 23:50:58 +00004070 RegisteredStructure structure = m_graph.registerStructure(
utatane.tea@gmail.com9d9fd322015-12-17 10:33:08 +00004071 isGeneratorFunction ? m_graph.globalObjectFor(m_node->origin.semantic)->generatorFunctionStructure() :
caitp@igalia.com8bc562d2016-11-14 21:14:15 +00004072 isAsyncFunction ? m_graph.globalObjectFor(m_node->origin.semantic)->asyncFunctionStructure() :
sbarati@apple.com239d20b2017-01-26 23:50:58 +00004073 m_graph.globalObjectFor(m_node->origin.semantic)->functionStructure());
commit-queue@webkit.org14aa0542015-04-17 00:44:58 +00004074
fpizlo@apple.com91331742016-03-07 02:07:28 +00004075 LBasicBlock slowPath = m_out.newBlock();
4076 LBasicBlock continuation = m_out.newBlock();
commit-queue@webkit.org14aa0542015-04-17 00:44:58 +00004077
4078 LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
4079
utatane.tea@gmail.com9d9fd322015-12-17 10:33:08 +00004080 LValue fastObject =
utatane.tea@gmail.com9d9fd322015-12-17 10:33:08 +00004081 isGeneratorFunction ? allocateObject<JSGeneratorFunction>(structure, m_out.intPtrZero, slowPath) :
4082 allocateObject<JSFunction>(structure, m_out.intPtrZero, slowPath);
commit-queue@webkit.orga4201b02015-08-17 22:24:20 +00004083
commit-queue@webkit.org14aa0542015-04-17 00:44:58 +00004084
4085 // We don't need memory barriers since we just fast-created the function, so it
4086 // must be young.
commit-queue@webkit.orga16c9f02016-01-11 01:38:36 +00004087 m_out.storePtr(scope, fastObject, m_heaps.JSFunction_scope);
4088 m_out.storePtr(weakPointer(executable), fastObject, m_heaps.JSFunction_executable);
4089 m_out.storePtr(m_out.intPtrZero, fastObject, m_heaps.JSFunction_rareData);
commit-queue@webkit.org14aa0542015-04-17 00:44:58 +00004090
fpizlo@apple.com101a1682016-11-15 01:49:22 +00004091 mutatorFence();
4092
commit-queue@webkit.org14aa0542015-04-17 00:44:58 +00004093 ValueFromBlock fastResult = m_out.anchor(fastObject);
4094 m_out.jump(continuation);
4095
4096 m_out.appendTo(slowPath, continuation);
fpizlo@apple.com6e697962015-10-12 17:56:26 +00004097
4098 Vector<LValue> slowPathArguments;
4099 slowPathArguments.append(scope);
fpizlo@apple.com6e697962015-10-12 17:56:26 +00004100 LValue callResult = lazySlowPath(
4101 [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
utatane.tea@gmail.com9d9fd322015-12-17 10:33:08 +00004102 if (isGeneratorFunction) {
4103 return createLazyCallGenerator(
4104 operationNewGeneratorFunctionWithInvalidatedReallocationWatchpoint,
4105 locations[0].directGPR(), locations[1].directGPR(),
4106 CCallHelpers::TrustedImmPtr(executable));
4107 }
caitp@igalia.com8bc562d2016-11-14 21:14:15 +00004108 if (isAsyncFunction) {
4109 return createLazyCallGenerator(
4110 operationNewAsyncFunctionWithInvalidatedReallocationWatchpoint,
4111 locations[0].directGPR(), locations[1].directGPR(),
4112 CCallHelpers::TrustedImmPtr(executable));
4113 }
fpizlo@apple.com6e697962015-10-12 17:56:26 +00004114 return createLazyCallGenerator(
4115 operationNewFunctionWithInvalidatedReallocationWatchpoint,
4116 locations[0].directGPR(), locations[1].directGPR(),
4117 CCallHelpers::TrustedImmPtr(executable));
4118 },
4119 slowPathArguments);
commit-queue@webkit.org14aa0542015-04-17 00:44:58 +00004120 ValueFromBlock slowResult = m_out.anchor(callResult);
4121 m_out.jump(continuation);
4122
4123 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00004124 setJSValue(m_out.phi(pointerType(), fastResult, slowResult));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004125 }
4126
4127 void compileCreateDirectArguments()
4128 {
4129 // FIXME: A more effective way of dealing with the argument count and callee is to have
4130 // them be explicit arguments to this node.
4131 // https://bugs.webkit.org/show_bug.cgi?id=142207
4132
sbarati@apple.com239d20b2017-01-26 23:50:58 +00004133 RegisteredStructure structure =
4134 m_graph.registerStructure(m_graph.globalObjectFor(m_node->origin.semantic)->directArgumentsStructure());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004135
4136 unsigned minCapacity = m_graph.baselineCodeBlockFor(m_node->origin.semantic)->numParameters() - 1;
4137
fpizlo@apple.com91331742016-03-07 02:07:28 +00004138 LBasicBlock slowPath = m_out.newBlock();
4139 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004140
4141 LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
4142
4143 ArgumentsLength length = getArgumentsLength();
4144
4145 LValue fastObject;
4146 if (length.isKnown) {
4147 fastObject = allocateObject<DirectArguments>(
4148 DirectArguments::allocationSize(std::max(length.known, minCapacity)), structure,
4149 m_out.intPtrZero, slowPath);
4150 } else {
4151 LValue size = m_out.add(
4152 m_out.shl(length.value, m_out.constInt32(3)),
4153 m_out.constInt32(DirectArguments::storageOffset()));
4154
4155 size = m_out.select(
4156 m_out.aboveOrEqual(length.value, m_out.constInt32(minCapacity)),
4157 size, m_out.constInt32(DirectArguments::allocationSize(minCapacity)));
4158
4159 fastObject = allocateVariableSizedObject<DirectArguments>(
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00004160 m_out.zeroExtPtr(size), structure, m_out.intPtrZero, slowPath);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004161 }
4162
4163 m_out.store32(length.value, fastObject, m_heaps.DirectArguments_length);
4164 m_out.store32(m_out.constInt32(minCapacity), fastObject, m_heaps.DirectArguments_minCapacity);
commit-queue@webkit.org812d82a2016-12-24 21:26:22 +00004165 m_out.storePtr(m_out.intPtrZero, fastObject, m_heaps.DirectArguments_mappedArguments);
4166 m_out.storePtr(m_out.intPtrZero, fastObject, m_heaps.DirectArguments_modifiedArgumentsDescriptor);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004167
4168 ValueFromBlock fastResult = m_out.anchor(fastObject);
4169 m_out.jump(continuation);
4170
4171 m_out.appendTo(slowPath, continuation);
fpizlo@apple.com6e697962015-10-12 17:56:26 +00004172 LValue callResult = lazySlowPath(
4173 [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
4174 return createLazyCallGenerator(
4175 operationCreateDirectArguments, locations[0].directGPR(),
sbarati@apple.com239d20b2017-01-26 23:50:58 +00004176 CCallHelpers::TrustedImmPtr(structure.get()), locations[1].directGPR(),
fpizlo@apple.com6e697962015-10-12 17:56:26 +00004177 CCallHelpers::TrustedImm32(minCapacity));
4178 }, length.value);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004179 ValueFromBlock slowResult = m_out.anchor(callResult);
4180 m_out.jump(continuation);
4181
4182 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00004183 LValue result = m_out.phi(pointerType(), fastResult, slowResult);
fpizlo@apple.com0582af42015-04-28 04:44:39 +00004184
4185 m_out.storePtr(getCurrentCallee(), result, m_heaps.DirectArguments_callee);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004186
4187 if (length.isKnown) {
4188 VirtualRegister start = AssemblyHelpers::argumentsStart(m_node->origin.semantic);
4189 for (unsigned i = 0; i < std::max(length.known, minCapacity); ++i) {
4190 m_out.store64(
4191 m_out.load64(addressFor(start + i)),
4192 result, m_heaps.DirectArguments_storage[i]);
4193 }
4194 } else {
4195 LValue stackBase = getArgumentsStart();
4196
fpizlo@apple.com91331742016-03-07 02:07:28 +00004197 LBasicBlock loop = m_out.newBlock();
4198 LBasicBlock end = m_out.newBlock();
fpizlo@apple.com373ed6b2015-12-15 04:52:55 +00004199
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004200 ValueFromBlock originalLength;
4201 if (minCapacity) {
4202 LValue capacity = m_out.select(
4203 m_out.aboveOrEqual(length.value, m_out.constInt32(minCapacity)),
4204 length.value,
4205 m_out.constInt32(minCapacity));
fpizlo@apple.com373ed6b2015-12-15 04:52:55 +00004206 LValue originalLengthValue = m_out.zeroExtPtr(capacity);
4207 originalLength = m_out.anchor(originalLengthValue);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004208 m_out.jump(loop);
4209 } else {
fpizlo@apple.com373ed6b2015-12-15 04:52:55 +00004210 LValue originalLengthValue = m_out.zeroExtPtr(length.value);
4211 originalLength = m_out.anchor(originalLengthValue);
4212 m_out.branch(m_out.isNull(originalLengthValue), unsure(end), unsure(loop));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004213 }
4214
4215 lastNext = m_out.appendTo(loop, end);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00004216 LValue previousIndex = m_out.phi(pointerType(), originalLength);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004217 LValue index = m_out.sub(previousIndex, m_out.intPtrOne);
4218 m_out.store64(
4219 m_out.load64(m_out.baseIndex(m_heaps.variables, stackBase, index)),
4220 m_out.baseIndex(m_heaps.DirectArguments_storage, result, index));
4221 ValueFromBlock nextIndex = m_out.anchor(index);
benjamin@webkit.org81ec96c2015-11-18 23:14:54 +00004222 m_out.addIncomingToPhi(previousIndex, nextIndex);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004223 m_out.branch(m_out.isNull(index), unsure(end), unsure(loop));
4224
4225 m_out.appendTo(end, lastNext);
4226 }
4227
fpizlo@apple.com101a1682016-11-15 01:49:22 +00004228 mutatorFence();
4229
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004230 setJSValue(result);
4231 }
4232
4233 void compileCreateScopedArguments()
4234 {
4235 LValue scope = lowCell(m_node->child1());
4236
4237 LValue result = vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00004238 Int64, m_out.operation(operationCreateScopedArguments), m_callFrame,
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004239 weakPointer(
4240 m_graph.globalObjectFor(m_node->origin.semantic)->scopedArgumentsStructure()),
4241 getArgumentsStart(), getArgumentsLength().value, getCurrentCallee(), scope);
4242
4243 setJSValue(result);
4244 }
4245
4246 void compileCreateClonedArguments()
4247 {
4248 LValue result = vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00004249 Int64, m_out.operation(operationCreateClonedArguments), m_callFrame,
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004250 weakPointer(
keith_miller@apple.com26367392016-03-14 20:55:15 +00004251 m_graph.globalObjectFor(m_node->origin.semantic)->clonedArgumentsStructure()),
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004252 getArgumentsStart(), getArgumentsLength().value, getCurrentCallee());
4253
4254 setJSValue(result);
4255 }
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004256
sbarati@apple.com6cfefd82016-08-13 02:14:42 +00004257 void compileCreateRest()
4258 {
4259 if (m_graph.isWatchingHavingABadTimeWatchpoint(m_node)) {
4260 LBasicBlock continuation = m_out.newBlock();
4261 LValue arrayLength = lowInt32(m_node->child1());
4262 LBasicBlock loopStart = m_out.newBlock();
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00004263 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
sbarati@apple.com239d20b2017-01-26 23:50:58 +00004264 RegisteredStructure structure = m_graph.registerStructure(globalObject->restParameterStructure());
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00004265 ArrayValues arrayValues = allocateUninitializedContiguousJSArray(arrayLength, structure);
4266 LValue array = arrayValues.array;
4267 LValue butterfly = arrayValues.butterfly;
sbarati@apple.com6cfefd82016-08-13 02:14:42 +00004268 ValueFromBlock startLength = m_out.anchor(arrayLength);
4269 LValue argumentRegion = m_out.add(getArgumentsStart(), m_out.constInt64(sizeof(Register) * m_node->numberOfArgumentsToSkip()));
4270 m_out.branch(m_out.equal(arrayLength, m_out.constInt32(0)),
4271 unsure(continuation), unsure(loopStart));
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004272
sbarati@apple.com6cfefd82016-08-13 02:14:42 +00004273 LBasicBlock lastNext = m_out.appendTo(loopStart, continuation);
4274 LValue phiOffset = m_out.phi(Int32, startLength);
4275 LValue currentOffset = m_out.sub(phiOffset, m_out.int32One);
4276 m_out.addIncomingToPhi(phiOffset, m_out.anchor(currentOffset));
4277 LValue loadedValue = m_out.load64(m_out.baseIndex(m_heaps.variables, argumentRegion, m_out.zeroExtPtr(currentOffset)));
4278 IndexedAbstractHeap& heap = m_heaps.indexedContiguousProperties;
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00004279 m_out.store64(loadedValue, m_out.baseIndex(heap, butterfly, m_out.zeroExtPtr(currentOffset)));
sbarati@apple.com6cfefd82016-08-13 02:14:42 +00004280 m_out.branch(m_out.equal(currentOffset, m_out.constInt32(0)), unsure(continuation), unsure(loopStart));
4281
4282 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com101a1682016-11-15 01:49:22 +00004283 mutatorFence();
sbarati@apple.com6cfefd82016-08-13 02:14:42 +00004284 setJSValue(array);
4285 return;
4286 }
4287
4288 LValue arrayLength = lowInt32(m_node->child1());
4289 LValue argumentStart = getArgumentsStart();
sbarati@apple.com855d5602015-11-30 20:36:54 +00004290 LValue numberOfArgumentsToSkip = m_out.constInt32(m_node->numberOfArgumentsToSkip());
sbarati@apple.com6cfefd82016-08-13 02:14:42 +00004291 setJSValue(vmCall(
4292 Int64, m_out.operation(operationCreateRest), m_callFrame, argumentStart, numberOfArgumentsToSkip, arrayLength));
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004293 }
sbarati@apple.com855d5602015-11-30 20:36:54 +00004294
4295 void compileGetRestLength()
4296 {
fpizlo@apple.com91331742016-03-07 02:07:28 +00004297 LBasicBlock nonZeroLength = m_out.newBlock();
4298 LBasicBlock continuation = m_out.newBlock();
sbarati@apple.com855d5602015-11-30 20:36:54 +00004299
4300 ValueFromBlock zeroLengthResult = m_out.anchor(m_out.constInt32(0));
4301
4302 LValue numberOfArgumentsToSkip = m_out.constInt32(m_node->numberOfArgumentsToSkip());
4303 LValue argumentsLength = getArgumentsLength().value;
4304 m_out.branch(m_out.above(argumentsLength, numberOfArgumentsToSkip),
4305 unsure(nonZeroLength), unsure(continuation));
4306
4307 LBasicBlock lastNext = m_out.appendTo(nonZeroLength, continuation);
4308 ValueFromBlock nonZeroLengthResult = m_out.anchor(m_out.sub(argumentsLength, numberOfArgumentsToSkip));
4309 m_out.jump(continuation);
4310
4311 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00004312 setInt32(m_out.phi(Int32, zeroLengthResult, nonZeroLengthResult));
sbarati@apple.com855d5602015-11-30 20:36:54 +00004313 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004314
fpizlo@apple.com1002a1d2013-11-06 04:40:02 +00004315 void compileNewObject()
4316 {
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00004317 setJSValue(allocateObject(m_node->structure()));
fpizlo@apple.com101a1682016-11-15 01:49:22 +00004318 mutatorFence();
fpizlo@apple.com1002a1d2013-11-06 04:40:02 +00004319 }
4320
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +00004321 void compileNewArray()
4322 {
4323 // First speculate appropriately on all of the children. Do this unconditionally up here
4324 // because some of the slow paths may otherwise forget to do it. It's sort of arguable
4325 // that doing the speculations up here might be unprofitable for RA - so we can consider
4326 // sinking this to below the allocation fast path if we find that this has a lot of
4327 // register pressure.
4328 for (unsigned operandIndex = 0; operandIndex < m_node->numChildren(); ++operandIndex)
4329 speculate(m_graph.varArgChild(m_node, operandIndex));
4330
fpizlo@apple.com6793a322014-02-12 05:42:32 +00004331 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
sbarati@apple.com239d20b2017-01-26 23:50:58 +00004332 RegisteredStructure structure = m_graph.registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(
4333 m_node->indexingType()));
fpizlo@apple.com35398ea2015-12-04 22:25:26 +00004334
dbatyai.u-szeged@partner.samsung.comb382e6d2014-03-26 15:08:12 +00004335 if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) {
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +00004336 unsigned numElements = m_node->numChildren();
4337
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00004338 ArrayValues arrayValues =
4339 allocateUninitializedContiguousJSArray(m_out.constInt32(numElements), structure);
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +00004340
4341 for (unsigned operandIndex = 0; operandIndex < m_node->numChildren(); ++operandIndex) {
4342 Edge edge = m_graph.varArgChild(m_node, operandIndex);
4343
4344 switch (m_node->indexingType()) {
4345 case ALL_BLANK_INDEXING_TYPES:
4346 case ALL_UNDECIDED_INDEXING_TYPES:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00004347 DFG_CRASH(m_graph, m_node, "Bad indexing type");
4348 break;
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +00004349
4350 case ALL_DOUBLE_INDEXING_TYPES:
4351 m_out.storeDouble(
4352 lowDouble(edge),
4353 arrayValues.butterfly, m_heaps.indexedDoubleProperties[operandIndex]);
4354 break;
4355
4356 case ALL_INT32_INDEXING_TYPES:
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +00004357 case ALL_CONTIGUOUS_INDEXING_TYPES:
4358 m_out.store64(
fpizlo@apple.comae909c12013-11-09 00:42:05 +00004359 lowJSValue(edge, ManualOperandSpeculation),
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +00004360 arrayValues.butterfly,
fpizlo@apple.comae909c12013-11-09 00:42:05 +00004361 m_heaps.forIndexingType(m_node->indexingType())->at(operandIndex));
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +00004362 break;
4363
4364 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00004365 DFG_CRASH(m_graph, m_node, "Corrupt indexing type");
4366 break;
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +00004367 }
4368 }
4369
4370 setJSValue(arrayValues.array);
fpizlo@apple.com101a1682016-11-15 01:49:22 +00004371 mutatorFence();
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +00004372 return;
4373 }
4374
4375 if (!m_node->numChildren()) {
4376 setJSValue(vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00004377 Int64, m_out.operation(operationNewEmptyArray), m_callFrame,
sbarati@apple.com239d20b2017-01-26 23:50:58 +00004378 weakStructure(structure)));
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +00004379 return;
4380 }
4381
4382 size_t scratchSize = sizeof(EncodedJSValue) * m_node->numChildren();
4383 ASSERT(scratchSize);
4384 ScratchBuffer* scratchBuffer = vm().scratchBufferForSize(scratchSize);
4385 EncodedJSValue* buffer = static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer());
4386
4387 for (unsigned operandIndex = 0; operandIndex < m_node->numChildren(); ++operandIndex) {
4388 Edge edge = m_graph.varArgChild(m_node, operandIndex);
fpizlo@apple.comae909c12013-11-09 00:42:05 +00004389 m_out.store64(
4390 lowJSValue(edge, ManualOperandSpeculation),
4391 m_out.absolute(buffer + operandIndex));
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +00004392 }
4393
4394 m_out.storePtr(
4395 m_out.constIntPtr(scratchSize), m_out.absolute(scratchBuffer->activeLengthPtr()));
4396
4397 LValue result = vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00004398 Int64, m_out.operation(operationNewArray), m_callFrame,
sbarati@apple.com239d20b2017-01-26 23:50:58 +00004399 weakStructure(structure), m_out.constIntPtr(buffer),
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +00004400 m_out.constIntPtr(m_node->numChildren()));
4401
4402 m_out.storePtr(m_out.intPtrZero, m_out.absolute(scratchBuffer->activeLengthPtr()));
4403
4404 setJSValue(result);
4405 }
sbarati@apple.com99ed4792016-11-12 02:58:11 +00004406
4407 void compileNewArrayWithSpread()
4408 {
4409 if (m_graph.isWatchingHavingABadTimeWatchpoint(m_node)) {
4410 unsigned startLength = 0;
4411 BitVector* bitVector = m_node->bitVector();
sbarati@apple.come20444a2016-11-30 06:24:44 +00004412 HashMap<InlineCallFrame*, LValue, WTF::DefaultHash<InlineCallFrame*>::Hash, WTF::NullableHashTraits<InlineCallFrame*>> cachedSpreadLengths;
4413
sbarati@apple.com99ed4792016-11-12 02:58:11 +00004414 for (unsigned i = 0; i < m_node->numChildren(); ++i) {
4415 if (!bitVector->get(i))
4416 ++startLength;
4417 }
4418
4419 LValue length = m_out.constInt32(startLength);
4420
4421 for (unsigned i = 0; i < m_node->numChildren(); ++i) {
4422 if (bitVector->get(i)) {
4423 Edge use = m_graph.varArgChild(m_node, i);
sbarati@apple.come20444a2016-11-30 06:24:44 +00004424 if (use->op() == PhantomSpread) {
4425 RELEASE_ASSERT(use->child1()->op() == PhantomCreateRest);
4426 InlineCallFrame* inlineCallFrame = use->child1()->origin.semantic.inlineCallFrame;
4427 unsigned numberOfArgumentsToSkip = use->child1()->numberOfArgumentsToSkip();
4428 LValue spreadLength = cachedSpreadLengths.ensure(inlineCallFrame, [&] () {
4429 return getSpreadLengthFromInlineCallFrame(inlineCallFrame, numberOfArgumentsToSkip);
4430 }).iterator->value;
4431 length = m_out.add(length, spreadLength);
4432 } else {
4433 LValue fixedArray = lowCell(use);
4434 length = m_out.add(length, m_out.load32(fixedArray, m_heaps.JSFixedArray_size));
4435 }
sbarati@apple.com99ed4792016-11-12 02:58:11 +00004436 }
4437 }
4438
sbarati@apple.com239d20b2017-01-26 23:50:58 +00004439 RegisteredStructure structure = m_graph.registerStructure(m_graph.globalObjectFor(m_node->origin.semantic)->originalArrayStructureForIndexingType(ArrayWithContiguous));
sbarati@apple.com99ed4792016-11-12 02:58:11 +00004440 ArrayValues arrayValues = allocateUninitializedContiguousJSArray(length, structure);
4441 LValue result = arrayValues.array;
4442 LValue storage = arrayValues.butterfly;
4443 LValue index = m_out.constIntPtr(0);
4444
4445 for (unsigned i = 0; i < m_node->numChildren(); ++i) {
4446 Edge use = m_graph.varArgChild(m_node, i);
4447 if (bitVector->get(i)) {
sbarati@apple.come20444a2016-11-30 06:24:44 +00004448 if (use->op() == PhantomSpread) {
4449 RELEASE_ASSERT(use->child1()->op() == PhantomCreateRest);
4450 InlineCallFrame* inlineCallFrame = use->child1()->origin.semantic.inlineCallFrame;
4451 unsigned numberOfArgumentsToSkip = use->child1()->numberOfArgumentsToSkip();
sbarati@apple.com99ed4792016-11-12 02:58:11 +00004452
sbarati@apple.come20444a2016-11-30 06:24:44 +00004453 LValue length = m_out.zeroExtPtr(cachedSpreadLengths.get(inlineCallFrame));
4454 LValue sourceStart = getArgumentsStart(inlineCallFrame, numberOfArgumentsToSkip);
sbarati@apple.com99ed4792016-11-12 02:58:11 +00004455
sbarati@apple.come20444a2016-11-30 06:24:44 +00004456 LBasicBlock loopStart = m_out.newBlock();
4457 LBasicBlock continuation = m_out.newBlock();
sbarati@apple.com99ed4792016-11-12 02:58:11 +00004458
sbarati@apple.come20444a2016-11-30 06:24:44 +00004459 ValueFromBlock loadIndexStart = m_out.anchor(m_out.constIntPtr(0));
4460 ValueFromBlock arrayIndexStart = m_out.anchor(index);
4461 ValueFromBlock arrayIndexStartForFinish = m_out.anchor(index);
sbarati@apple.com99ed4792016-11-12 02:58:11 +00004462
sbarati@apple.come20444a2016-11-30 06:24:44 +00004463 m_out.branch(
4464 m_out.isZero64(length),
4465 unsure(continuation), unsure(loopStart));
sbarati@apple.com99ed4792016-11-12 02:58:11 +00004466
sbarati@apple.come20444a2016-11-30 06:24:44 +00004467 LBasicBlock lastNext = m_out.appendTo(loopStart, continuation);
sbarati@apple.com99ed4792016-11-12 02:58:11 +00004468
sbarati@apple.come20444a2016-11-30 06:24:44 +00004469 LValue arrayIndex = m_out.phi(pointerType(), arrayIndexStart);
4470 LValue loadIndex = m_out.phi(pointerType(), loadIndexStart);
sbarati@apple.com99ed4792016-11-12 02:58:11 +00004471
sbarati@apple.come20444a2016-11-30 06:24:44 +00004472 LValue item = m_out.load64(m_out.baseIndex(m_heaps.variables, sourceStart, loadIndex));
4473 m_out.store64(item, m_out.baseIndex(m_heaps.indexedContiguousProperties, storage, arrayIndex));
sbarati@apple.com99ed4792016-11-12 02:58:11 +00004474
sbarati@apple.come20444a2016-11-30 06:24:44 +00004475 LValue nextArrayIndex = m_out.add(arrayIndex, m_out.constIntPtr(1));
4476 LValue nextLoadIndex = m_out.add(loadIndex, m_out.constIntPtr(1));
4477 ValueFromBlock arrayIndexLoopForFinish = m_out.anchor(nextArrayIndex);
sbarati@apple.com99ed4792016-11-12 02:58:11 +00004478
sbarati@apple.come20444a2016-11-30 06:24:44 +00004479 m_out.addIncomingToPhi(loadIndex, m_out.anchor(nextLoadIndex));
4480 m_out.addIncomingToPhi(arrayIndex, m_out.anchor(nextArrayIndex));
sbarati@apple.com99ed4792016-11-12 02:58:11 +00004481
sbarati@apple.come20444a2016-11-30 06:24:44 +00004482 m_out.branch(
4483 m_out.below(nextLoadIndex, length),
4484 unsure(loopStart), unsure(continuation));
sbarati@apple.com99ed4792016-11-12 02:58:11 +00004485
sbarati@apple.come20444a2016-11-30 06:24:44 +00004486 m_out.appendTo(continuation, lastNext);
4487 index = m_out.phi(pointerType(), arrayIndexStartForFinish, arrayIndexLoopForFinish);
4488 } else {
4489 LBasicBlock loopStart = m_out.newBlock();
4490 LBasicBlock continuation = m_out.newBlock();
4491
4492 LValue fixedArray = lowCell(use);
4493
4494 ValueFromBlock fixedIndexStart = m_out.anchor(m_out.constIntPtr(0));
4495 ValueFromBlock arrayIndexStart = m_out.anchor(index);
4496 ValueFromBlock arrayIndexStartForFinish = m_out.anchor(index);
4497
4498 LValue fixedArraySize = m_out.zeroExtPtr(m_out.load32(fixedArray, m_heaps.JSFixedArray_size));
4499
4500 m_out.branch(
4501 m_out.isZero64(fixedArraySize),
4502 unsure(continuation), unsure(loopStart));
4503
4504 LBasicBlock lastNext = m_out.appendTo(loopStart, continuation);
4505
4506 LValue arrayIndex = m_out.phi(pointerType(), arrayIndexStart);
4507 LValue fixedArrayIndex = m_out.phi(pointerType(), fixedIndexStart);
4508
4509 LValue item = m_out.load64(m_out.baseIndex(m_heaps.JSFixedArray_buffer, fixedArray, fixedArrayIndex));
4510 m_out.store64(item, m_out.baseIndex(m_heaps.indexedContiguousProperties, storage, arrayIndex));
4511
4512 LValue nextArrayIndex = m_out.add(arrayIndex, m_out.constIntPtr(1));
4513 LValue nextFixedArrayIndex = m_out.add(fixedArrayIndex, m_out.constIntPtr(1));
4514 ValueFromBlock arrayIndexLoopForFinish = m_out.anchor(nextArrayIndex);
4515
4516 m_out.addIncomingToPhi(fixedArrayIndex, m_out.anchor(nextFixedArrayIndex));
4517 m_out.addIncomingToPhi(arrayIndex, m_out.anchor(nextArrayIndex));
4518
4519 m_out.branch(
4520 m_out.below(nextFixedArrayIndex, fixedArraySize),
4521 unsure(loopStart), unsure(continuation));
4522
4523 m_out.appendTo(continuation, lastNext);
4524 index = m_out.phi(pointerType(), arrayIndexStartForFinish, arrayIndexLoopForFinish);
4525 }
sbarati@apple.com99ed4792016-11-12 02:58:11 +00004526 } else {
4527 IndexedAbstractHeap& heap = m_heaps.indexedContiguousProperties;
4528 LValue item = lowJSValue(use);
4529 m_out.store64(item, m_out.baseIndex(heap, storage, index));
4530 index = m_out.add(index, m_out.constIntPtr(1));
4531 }
4532 }
4533
fpizlo@apple.com101a1682016-11-15 01:49:22 +00004534 mutatorFence();
sbarati@apple.com99ed4792016-11-12 02:58:11 +00004535 setJSValue(result);
4536 return;
4537 }
4538
4539 ASSERT(m_node->numChildren());
4540 size_t scratchSize = sizeof(EncodedJSValue) * m_node->numChildren();
4541 ScratchBuffer* scratchBuffer = vm().scratchBufferForSize(scratchSize);
4542 EncodedJSValue* buffer = static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer());
4543 BitVector* bitVector = m_node->bitVector();
4544 for (unsigned i = 0; i < m_node->numChildren(); ++i) {
4545 Edge use = m_graph.m_varArgChildren[m_node->firstChild() + i];
4546 LValue value;
4547 if (bitVector->get(i))
4548 value = lowCell(use);
4549 else
4550 value = lowJSValue(use);
4551 m_out.store64(value, m_out.absolute(&buffer[i]));
4552 }
4553
4554 m_out.storePtr(m_out.constIntPtr(scratchSize), m_out.absolute(scratchBuffer->activeLengthPtr()));
4555 LValue result = vmCall(Int64, m_out.operation(operationNewArrayWithSpreadSlow), m_callFrame, m_out.constIntPtr(buffer), m_out.constInt32(m_node->numChildren()));
4556 m_out.storePtr(m_out.constIntPtr(0), m_out.absolute(scratchBuffer->activeLengthPtr()));
4557
4558 setJSValue(result);
4559 }
4560
4561 void compileSpread()
4562 {
sbarati@apple.come20444a2016-11-30 06:24:44 +00004563 // It would be trivial to support this, but for now, we never create
4564 // IR that would necessitate this. The reason is that Spread is only
4565 // consumed by NewArrayWithSpread and never anything else. Also, any
4566 // Spread(PhantomCreateRest) will turn into PhantomSpread(PhantomCreateRest).
4567 RELEASE_ASSERT(m_node->child1()->op() != PhantomCreateRest);
4568
sbarati@apple.com99ed4792016-11-12 02:58:11 +00004569 LValue argument = lowCell(m_node->child1());
4570
4571 LValue result;
4572 if (m_node->child1().useKind() == ArrayUse) {
4573 speculateArray(m_node->child1());
4574
4575 LBasicBlock preLoop = m_out.newBlock();
4576 LBasicBlock loopSelection = m_out.newBlock();
4577 LBasicBlock contiguousLoopStart = m_out.newBlock();
4578 LBasicBlock doubleLoopStart = m_out.newBlock();
4579 LBasicBlock slowPath = m_out.newBlock();
4580 LBasicBlock continuation = m_out.newBlock();
4581
fpizlo@apple.com101a1682016-11-15 01:49:22 +00004582 LValue indexingShape = m_out.load8ZeroExt32(argument, m_heaps.JSCell_indexingTypeAndMisc);
sbarati@apple.com99ed4792016-11-12 02:58:11 +00004583 indexingShape = m_out.bitAnd(indexingShape, m_out.constInt32(IndexingShapeMask));
4584 LValue isOKIndexingType = m_out.belowOrEqual(
4585 m_out.sub(indexingShape, m_out.constInt32(Int32Shape)),
4586 m_out.constInt32(ContiguousShape - Int32Shape));
4587
4588 m_out.branch(isOKIndexingType, unsure(preLoop), unsure(slowPath));
4589 LBasicBlock lastNext = m_out.appendTo(preLoop, loopSelection);
4590
4591 LValue butterfly = m_out.loadPtr(argument, m_heaps.JSObject_butterfly);
4592 LValue length = m_out.load32NonNegative(butterfly, m_heaps.Butterfly_publicLength);
4593 static_assert(sizeof(JSValue) == 8 && 1 << 3 == 8, "Assumed in the code below.");
4594 LValue size = m_out.add(
4595 m_out.shl(m_out.zeroExtPtr(length), m_out.constInt32(3)),
4596 m_out.constIntPtr(JSFixedArray::offsetOfData()));
4597
4598 LValue fastAllocation = allocateVariableSizedCell<JSFixedArray>(size, m_graph.m_vm.fixedArrayStructure.get(), slowPath);
4599 ValueFromBlock fastResult = m_out.anchor(fastAllocation);
4600 m_out.store32(length, fastAllocation, m_heaps.JSFixedArray_size);
4601
4602 ValueFromBlock startIndexForContiguous = m_out.anchor(m_out.constIntPtr(0));
4603 ValueFromBlock startIndexForDouble = m_out.anchor(m_out.constIntPtr(0));
4604
4605 m_out.branch(m_out.isZero32(length), unsure(continuation), unsure(loopSelection));
4606
4607 m_out.appendTo(loopSelection, contiguousLoopStart);
4608 m_out.branch(m_out.equal(indexingShape, m_out.constInt32(DoubleShape)),
4609 unsure(doubleLoopStart), unsure(contiguousLoopStart));
4610
4611 {
4612 m_out.appendTo(contiguousLoopStart, doubleLoopStart);
4613 LValue index = m_out.phi(pointerType(), startIndexForContiguous);
4614
4615 TypedPointer loadSite = m_out.baseIndex(m_heaps.root, butterfly, index, ScaleEight); // We read TOP here since we can be reading either int32 or contiguous properties.
4616 LValue value = m_out.load64(loadSite);
4617 value = m_out.select(m_out.isZero64(value), m_out.constInt64(JSValue::encode(jsUndefined())), value);
4618 m_out.store64(value, m_out.baseIndex(m_heaps.JSFixedArray_buffer, fastAllocation, index));
4619
4620 LValue nextIndex = m_out.add(index, m_out.constIntPtr(1));
4621 m_out.addIncomingToPhi(index, m_out.anchor(nextIndex));
4622
4623 m_out.branch(m_out.below(nextIndex, m_out.zeroExtPtr(length)),
4624 unsure(contiguousLoopStart), unsure(continuation));
4625 }
4626
4627 {
4628 m_out.appendTo(doubleLoopStart, slowPath);
4629 LValue index = m_out.phi(pointerType(), startIndexForDouble);
4630
4631 LValue value = m_out.loadDouble(m_out.baseIndex(m_heaps.indexedDoubleProperties, butterfly, index));
4632 LValue isNaN = m_out.doubleNotEqualOrUnordered(value, value);
4633 LValue holeResult = m_out.constInt64(JSValue::encode(jsUndefined()));
4634 LValue normalResult = boxDouble(value);
4635 value = m_out.select(isNaN, holeResult, normalResult);
4636 m_out.store64(value, m_out.baseIndex(m_heaps.JSFixedArray_buffer, fastAllocation, index));
4637
4638 LValue nextIndex = m_out.add(index, m_out.constIntPtr(1));
4639 m_out.addIncomingToPhi(index, m_out.anchor(nextIndex));
4640
4641 m_out.branch(m_out.below(nextIndex, m_out.zeroExtPtr(length)),
4642 unsure(doubleLoopStart), unsure(continuation));
4643 }
4644
4645 m_out.appendTo(slowPath, continuation);
4646 ValueFromBlock slowResult = m_out.anchor(vmCall(Int64, m_out.operation(operationSpreadFastArray), m_callFrame, argument));
4647 m_out.jump(continuation);
4648
4649 m_out.appendTo(continuation, lastNext);
4650 result = m_out.phi(Int64, fastResult, slowResult);
fpizlo@apple.com101a1682016-11-15 01:49:22 +00004651 mutatorFence();
sbarati@apple.com99ed4792016-11-12 02:58:11 +00004652 } else
4653 result = vmCall(Int64, m_out.operation(operationSpreadGeneric), m_callFrame, argument);
4654
4655 setJSValue(result);
4656 }
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +00004657
fpizlo@apple.comae909c12013-11-09 00:42:05 +00004658 void compileNewArrayBuffer()
4659 {
fpizlo@apple.com6793a322014-02-12 05:42:32 +00004660 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
sbarati@apple.com239d20b2017-01-26 23:50:58 +00004661 RegisteredStructure structure = m_graph.registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(
4662 m_node->indexingType()));
fpizlo@apple.comae909c12013-11-09 00:42:05 +00004663
dbatyai.u-szeged@partner.samsung.comb382e6d2014-03-26 15:08:12 +00004664 if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) {
fpizlo@apple.comae909c12013-11-09 00:42:05 +00004665 unsigned numElements = m_node->numConstants();
4666
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00004667 ArrayValues arrayValues =
4668 allocateUninitializedContiguousJSArray(m_out.constInt32(numElements), structure);
fpizlo@apple.comae909c12013-11-09 00:42:05 +00004669
4670 JSValue* data = codeBlock()->constantBuffer(m_node->startConstant());
4671 for (unsigned index = 0; index < m_node->numConstants(); ++index) {
4672 int64_t value;
4673 if (hasDouble(m_node->indexingType()))
4674 value = bitwise_cast<int64_t>(data[index].asNumber());
4675 else
4676 value = JSValue::encode(data[index]);
4677
4678 m_out.store64(
4679 m_out.constInt64(value),
4680 arrayValues.butterfly,
4681 m_heaps.forIndexingType(m_node->indexingType())->at(index));
4682 }
4683
fpizlo@apple.com101a1682016-11-15 01:49:22 +00004684 mutatorFence();
fpizlo@apple.comae909c12013-11-09 00:42:05 +00004685 setJSValue(arrayValues.array);
4686 return;
4687 }
4688
4689 setJSValue(vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00004690 Int64, m_out.operation(operationNewArrayBuffer), m_callFrame,
sbarati@apple.com239d20b2017-01-26 23:50:58 +00004691 weakStructure(structure), m_out.constIntPtr(m_node->startConstant()),
fpizlo@apple.comae909c12013-11-09 00:42:05 +00004692 m_out.constIntPtr(m_node->numConstants())));
4693 }
sbarati@apple.com6cfefd82016-08-13 02:14:42 +00004694
msaboff@apple.com95894332014-01-29 19:18:54 +00004695 void compileNewArrayWithSize()
4696 {
4697 LValue publicLength = lowInt32(m_node->child1());
4698
fpizlo@apple.com6793a322014-02-12 05:42:32 +00004699 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
sbarati@apple.com239d20b2017-01-26 23:50:58 +00004700 RegisteredStructure structure = m_graph.registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(
4701 m_node->indexingType()));
msaboff@apple.com95894332014-01-29 19:18:54 +00004702
dbatyai.u-szeged@partner.samsung.comb382e6d2014-03-26 15:08:12 +00004703 if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) {
sbarati@apple.comfd407a52017-01-13 04:03:47 +00004704 IndexingType indexingType = m_node->indexingType();
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00004705 setJSValue(
4706 allocateJSArray(
sbarati@apple.com239d20b2017-01-26 23:50:58 +00004707 publicLength, weakPointer(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType)), m_out.constInt32(indexingType)).array);
fpizlo@apple.com101a1682016-11-15 01:49:22 +00004708 mutatorFence();
msaboff@apple.com95894332014-01-29 19:18:54 +00004709 return;
4710 }
4711
4712 LValue structureValue = m_out.select(
fpizlo@apple.comc8f36872015-05-05 02:40:28 +00004713 m_out.aboveOrEqual(publicLength, m_out.constInt32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)),
sbarati@apple.com239d20b2017-01-26 23:50:58 +00004714 weakStructure(m_graph.registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage))),
4715 weakStructure(structure));
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00004716 setJSValue(vmCall(Int64, m_out.operation(operationNewArrayWithSize), m_callFrame, structureValue, publicLength, m_out.intPtrZero));
msaboff@apple.com95894332014-01-29 19:18:54 +00004717 }
fpizlo@apple.com3bbf1b92016-02-17 04:25:57 +00004718
4719 void compileNewTypedArray()
4720 {
4721 TypedArrayType type = m_node->typedArrayType();
4722 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
4723
4724 switch (m_node->child1().useKind()) {
4725 case Int32Use: {
sbarati@apple.com239d20b2017-01-26 23:50:58 +00004726 RegisteredStructure structure = m_graph.registerStructure(globalObject->typedArrayStructureConcurrently(type));
fpizlo@apple.com3bbf1b92016-02-17 04:25:57 +00004727
4728 LValue size = lowInt32(m_node->child1());
4729
fpizlo@apple.com91331742016-03-07 02:07:28 +00004730 LBasicBlock smallEnoughCase = m_out.newBlock();
4731 LBasicBlock nonZeroCase = m_out.newBlock();
4732 LBasicBlock slowCase = m_out.newBlock();
4733 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com30a72582016-09-08 16:47:34 +00004734
4735 ValueFromBlock noStorage = m_out.anchor(m_out.intPtrZero);
fpizlo@apple.com3bbf1b92016-02-17 04:25:57 +00004736
4737 m_out.branch(
4738 m_out.above(size, m_out.constInt32(JSArrayBufferView::fastSizeLimit)),
4739 rarely(slowCase), usually(smallEnoughCase));
4740
4741 LBasicBlock lastNext = m_out.appendTo(smallEnoughCase, nonZeroCase);
4742
4743 m_out.branch(m_out.notZero32(size), usually(nonZeroCase), rarely(slowCase));
4744
4745 m_out.appendTo(nonZeroCase, slowCase);
4746
4747 LValue byteSize =
4748 m_out.shl(m_out.zeroExtPtr(size), m_out.constInt32(logElementSize(type)));
4749 if (elementSize(type) < 8) {
4750 byteSize = m_out.bitAnd(
4751 m_out.add(byteSize, m_out.constIntPtr(7)),
4752 m_out.constIntPtr(~static_cast<intptr_t>(7)));
4753 }
4754
fpizlo@apple.com5fa9d962017-01-18 04:22:45 +00004755 LValue allocator = allocatorForSize(vm().auxiliarySpace, byteSize, slowCase);
fpizlo@apple.com30a72582016-09-08 16:47:34 +00004756 LValue storage = allocateHeapCell(allocator, slowCase);
4757
4758 splatWords(
4759 storage,
4760 m_out.int32Zero,
4761 m_out.castToInt32(m_out.lShr(byteSize, m_out.constIntPtr(3))),
4762 m_out.int64Zero,
4763 m_heaps.typedArrayProperties);
4764
4765 ValueFromBlock haveStorage = m_out.anchor(storage);
fpizlo@apple.com3bbf1b92016-02-17 04:25:57 +00004766
4767 LValue fastResultValue =
4768 allocateObject<JSArrayBufferView>(structure, m_out.intPtrZero, slowCase);
4769
4770 m_out.storePtr(storage, fastResultValue, m_heaps.JSArrayBufferView_vector);
4771 m_out.store32(size, fastResultValue, m_heaps.JSArrayBufferView_length);
4772 m_out.store32(m_out.constInt32(FastTypedArray), fastResultValue, m_heaps.JSArrayBufferView_mode);
fpizlo@apple.com30a72582016-09-08 16:47:34 +00004773
fpizlo@apple.com101a1682016-11-15 01:49:22 +00004774 mutatorFence();
fpizlo@apple.com3bbf1b92016-02-17 04:25:57 +00004775 ValueFromBlock fastResult = m_out.anchor(fastResultValue);
4776 m_out.jump(continuation);
4777
4778 m_out.appendTo(slowCase, continuation);
fpizlo@apple.com30a72582016-09-08 16:47:34 +00004779 LValue storageValue = m_out.phi(pointerType(), noStorage, haveStorage);
fpizlo@apple.com3bbf1b92016-02-17 04:25:57 +00004780
4781 LValue slowResultValue = lazySlowPath(
4782 [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
4783 return createLazyCallGenerator(
4784 operationNewTypedArrayWithSizeForType(type), locations[0].directGPR(),
sbarati@apple.com239d20b2017-01-26 23:50:58 +00004785 CCallHelpers::TrustedImmPtr(structure.get()), locations[1].directGPR(),
fpizlo@apple.com30a72582016-09-08 16:47:34 +00004786 locations[2].directGPR());
fpizlo@apple.com3bbf1b92016-02-17 04:25:57 +00004787 },
fpizlo@apple.com30a72582016-09-08 16:47:34 +00004788 size, storageValue);
fpizlo@apple.com3bbf1b92016-02-17 04:25:57 +00004789 ValueFromBlock slowResult = m_out.anchor(slowResultValue);
4790 m_out.jump(continuation);
4791
4792 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00004793 setJSValue(m_out.phi(pointerType(), fastResult, slowResult));
fpizlo@apple.com3bbf1b92016-02-17 04:25:57 +00004794 return;
4795 }
4796
4797 case UntypedUse: {
4798 LValue argument = lowJSValue(m_node->child1());
4799
4800 LValue result = vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00004801 pointerType(), m_out.operation(operationNewTypedArrayWithOneArgumentForType(type)),
fpizlo@apple.comcff2d0c2016-05-04 21:21:36 +00004802 m_callFrame, weakPointer(globalObject->typedArrayStructureConcurrently(type)), argument);
fpizlo@apple.com3bbf1b92016-02-17 04:25:57 +00004803
4804 setJSValue(result);
4805 return;
4806 }
4807
4808 default:
4809 DFG_CRASH(m_graph, m_node, "Bad use kind");
4810 return;
4811 }
4812 }
msaboff@apple.com95894332014-01-29 19:18:54 +00004813
fpizlo@apple.come962af32013-11-09 01:44:56 +00004814 void compileAllocatePropertyStorage()
4815 {
fpizlo@apple.come962af32013-11-09 01:44:56 +00004816 LValue object = lowCell(m_node->child1());
sbarati@apple.com239d20b2017-01-26 23:50:58 +00004817 setStorage(allocatePropertyStorage(object, m_node->transition()->previous.get()));
fpizlo@apple.come962af32013-11-09 01:44:56 +00004818 }
commit-queue@webkit.org7cd99852014-02-11 01:31:41 +00004819
4820 void compileReallocatePropertyStorage()
4821 {
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +00004822 Transition* transition = m_node->transition();
commit-queue@webkit.org7cd99852014-02-11 01:31:41 +00004823 LValue object = lowCell(m_node->child1());
fpizlo@apple.com43219522014-02-25 02:02:50 +00004824 LValue oldStorage = lowStorage(m_node->child2());
commit-queue@webkit.org7cd99852014-02-11 01:31:41 +00004825
fpizlo@apple.com43219522014-02-25 02:02:50 +00004826 setStorage(
4827 reallocatePropertyStorage(
sbarati@apple.com239d20b2017-01-26 23:50:58 +00004828 object, oldStorage, transition->previous.get(), transition->next.get()));
commit-queue@webkit.org7cd99852014-02-11 01:31:41 +00004829 }
fpizlo@apple.comb0e7f3d2016-12-10 01:22:15 +00004830
4831 void compileNukeStructureAndSetButterfly()
4832 {
4833 nukeStructureAndSetButterfly(lowStorage(m_node->child2()), lowCell(m_node->child1()));
4834 }
utatane.tea@gmail.comdb32c542016-06-30 15:26:47 +00004835
4836 void compileToNumber()
4837 {
4838 LValue value = lowJSValue(m_node->child1());
4839
4840 if (!(abstractValue(m_node->child1()).m_type & SpecBytecodeNumber))
fpizlo@apple.com994d4532016-07-03 19:34:55 +00004841 setJSValue(vmCall(Int64, m_out.operation(operationToNumber), m_callFrame, value));
utatane.tea@gmail.comdb32c542016-06-30 15:26:47 +00004842 else {
4843 LBasicBlock notNumber = m_out.newBlock();
4844 LBasicBlock continuation = m_out.newBlock();
4845
4846 ValueFromBlock fastResult = m_out.anchor(value);
4847 m_out.branch(isNumber(value, provenType(m_node->child1())), unsure(continuation), unsure(notNumber));
4848
4849 // notNumber case.
4850 LBasicBlock lastNext = m_out.appendTo(notNumber, continuation);
4851 // We have several attempts to remove ToNumber. But ToNumber still exists.
4852 // It means that converting non-numbers to numbers by this ToNumber is not rare.
4853 // Instead of the lazy slow path generator, we call the operation here.
fpizlo@apple.com994d4532016-07-03 19:34:55 +00004854 ValueFromBlock slowResult = m_out.anchor(vmCall(Int64, m_out.operation(operationToNumber), m_callFrame, value));
utatane.tea@gmail.comdb32c542016-06-30 15:26:47 +00004855 m_out.jump(continuation);
4856
4857 // continuation case.
4858 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00004859 setJSValue(m_out.phi(Int64, fastResult, slowResult));
utatane.tea@gmail.comdb32c542016-06-30 15:26:47 +00004860 }
4861 }
commit-queue@webkit.org7cd99852014-02-11 01:31:41 +00004862
utatane.tea@gmail.com153559e2015-04-06 19:07:12 +00004863 void compileToStringOrCallStringConstructor()
msaboff@apple.com95894332014-01-29 19:18:54 +00004864 {
4865 switch (m_node->child1().useKind()) {
4866 case StringObjectUse: {
4867 LValue cell = lowCell(m_node->child1());
4868 speculateStringObjectForCell(m_node->child1(), cell);
4869 m_interpreter.filter(m_node->child1(), SpecStringObject);
4870
4871 setJSValue(m_out.loadPtr(cell, m_heaps.JSWrapperObject_internalValue));
4872 return;
4873 }
4874
4875 case StringOrStringObjectUse: {
4876 LValue cell = lowCell(m_node->child1());
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +00004877 LValue structureID = m_out.load32(cell, m_heaps.JSCell_structureID);
msaboff@apple.com95894332014-01-29 19:18:54 +00004878
fpizlo@apple.com91331742016-03-07 02:07:28 +00004879 LBasicBlock notString = m_out.newBlock();
4880 LBasicBlock continuation = m_out.newBlock();
msaboff@apple.com95894332014-01-29 19:18:54 +00004881
4882 ValueFromBlock simpleResult = m_out.anchor(cell);
4883 m_out.branch(
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +00004884 m_out.equal(structureID, m_out.constInt32(vm().stringStructure->id())),
fpizlo@apple.com975ae502014-02-19 22:29:43 +00004885 unsure(continuation), unsure(notString));
msaboff@apple.com95894332014-01-29 19:18:54 +00004886
4887 LBasicBlock lastNext = m_out.appendTo(notString, continuation);
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +00004888 speculateStringObjectForStructureID(m_node->child1(), structureID);
msaboff@apple.com95894332014-01-29 19:18:54 +00004889 ValueFromBlock unboxedResult = m_out.anchor(
4890 m_out.loadPtr(cell, m_heaps.JSWrapperObject_internalValue));
4891 m_out.jump(continuation);
4892
4893 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00004894 setJSValue(m_out.phi(Int64, simpleResult, unboxedResult));
msaboff@apple.com95894332014-01-29 19:18:54 +00004895
4896 m_interpreter.filter(m_node->child1(), SpecString | SpecStringObject);
4897 return;
4898 }
4899
4900 case CellUse:
4901 case UntypedUse: {
4902 LValue value;
4903 if (m_node->child1().useKind() == CellUse)
4904 value = lowCell(m_node->child1());
4905 else
4906 value = lowJSValue(m_node->child1());
4907
fpizlo@apple.com91331742016-03-07 02:07:28 +00004908 LBasicBlock isCell = m_out.newBlock();
4909 LBasicBlock notString = m_out.newBlock();
4910 LBasicBlock continuation = m_out.newBlock();
msaboff@apple.com95894332014-01-29 19:18:54 +00004911
4912 LValue isCellPredicate;
4913 if (m_node->child1().useKind() == CellUse)
4914 isCellPredicate = m_out.booleanTrue;
4915 else
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00004916 isCellPredicate = this->isCell(value, provenType(m_node->child1()));
fpizlo@apple.com975ae502014-02-19 22:29:43 +00004917 m_out.branch(isCellPredicate, unsure(isCell), unsure(notString));
msaboff@apple.com95894332014-01-29 19:18:54 +00004918
4919 LBasicBlock lastNext = m_out.appendTo(isCell, notString);
4920 ValueFromBlock simpleResult = m_out.anchor(value);
4921 LValue isStringPredicate;
4922 if (m_node->child1()->prediction() & SpecString) {
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00004923 isStringPredicate = isString(value, provenType(m_node->child1()));
msaboff@apple.com95894332014-01-29 19:18:54 +00004924 } else
4925 isStringPredicate = m_out.booleanFalse;
fpizlo@apple.com975ae502014-02-19 22:29:43 +00004926 m_out.branch(isStringPredicate, unsure(continuation), unsure(notString));
msaboff@apple.com95894332014-01-29 19:18:54 +00004927
4928 m_out.appendTo(notString, continuation);
4929 LValue operation;
4930 if (m_node->child1().useKind() == CellUse)
utatane.tea@gmail.com153559e2015-04-06 19:07:12 +00004931 operation = m_out.operation(m_node->op() == ToString ? operationToStringOnCell : operationCallStringConstructorOnCell);
msaboff@apple.com95894332014-01-29 19:18:54 +00004932 else
utatane.tea@gmail.com153559e2015-04-06 19:07:12 +00004933 operation = m_out.operation(m_node->op() == ToString ? operationToString : operationCallStringConstructor);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00004934 ValueFromBlock convertedResult = m_out.anchor(vmCall(Int64, operation, m_callFrame, value));
msaboff@apple.com95894332014-01-29 19:18:54 +00004935 m_out.jump(continuation);
4936
4937 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00004938 setJSValue(m_out.phi(Int64, simpleResult, convertedResult));
msaboff@apple.com95894332014-01-29 19:18:54 +00004939 return;
4940 }
4941
4942 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00004943 DFG_CRASH(m_graph, m_node, "Bad use kind");
4944 break;
msaboff@apple.com95894332014-01-29 19:18:54 +00004945 }
4946 }
4947
fpizlo@apple.com6e550a42014-02-17 20:23:34 +00004948 void compileToPrimitive()
4949 {
4950 LValue value = lowJSValue(m_node->child1());
4951
fpizlo@apple.com91331742016-03-07 02:07:28 +00004952 LBasicBlock isCellCase = m_out.newBlock();
4953 LBasicBlock isObjectCase = m_out.newBlock();
4954 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com6e550a42014-02-17 20:23:34 +00004955
4956 Vector<ValueFromBlock, 3> results;
4957
4958 results.append(m_out.anchor(value));
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00004959 m_out.branch(
4960 isCell(value, provenType(m_node->child1())), unsure(isCellCase), unsure(continuation));
fpizlo@apple.com6e550a42014-02-17 20:23:34 +00004961
4962 LBasicBlock lastNext = m_out.appendTo(isCellCase, isObjectCase);
4963 results.append(m_out.anchor(value));
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00004964 m_out.branch(
4965 isObject(value, provenType(m_node->child1())),
4966 unsure(isObjectCase), unsure(continuation));
fpizlo@apple.com6e550a42014-02-17 20:23:34 +00004967
4968 m_out.appendTo(isObjectCase, continuation);
4969 results.append(m_out.anchor(vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00004970 Int64, m_out.operation(operationToPrimitive), m_callFrame, value)));
fpizlo@apple.com6e550a42014-02-17 20:23:34 +00004971 m_out.jump(continuation);
4972
4973 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00004974 setJSValue(m_out.phi(Int64, results));
fpizlo@apple.com6e550a42014-02-17 20:23:34 +00004975 }
4976
msaboff@apple.com95894332014-01-29 19:18:54 +00004977 void compileMakeRope()
4978 {
4979 LValue kids[3];
4980 unsigned numKids;
4981 kids[0] = lowCell(m_node->child1());
4982 kids[1] = lowCell(m_node->child2());
4983 if (m_node->child3()) {
4984 kids[2] = lowCell(m_node->child3());
4985 numKids = 3;
4986 } else {
4987 kids[2] = 0;
4988 numKids = 2;
4989 }
4990
fpizlo@apple.com91331742016-03-07 02:07:28 +00004991 LBasicBlock slowPath = m_out.newBlock();
4992 LBasicBlock continuation = m_out.newBlock();
msaboff@apple.com95894332014-01-29 19:18:54 +00004993
4994 LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
4995
fpizlo@apple.com5fa9d962017-01-18 04:22:45 +00004996 MarkedAllocator* allocator = subspaceFor<JSRopeString>(vm())->allocatorFor(sizeof(JSRopeString));
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00004997 DFG_ASSERT(m_graph, m_node, allocator);
msaboff@apple.com95894332014-01-29 19:18:54 +00004998
4999 LValue result = allocateCell(
commit-queue@webkit.org3194ff32016-11-30 20:30:16 +00005000 m_out.constIntPtr(allocator), vm().stringStructure.get(), slowPath);
msaboff@apple.com95894332014-01-29 19:18:54 +00005001
5002 m_out.storePtr(m_out.intPtrZero, result, m_heaps.JSString_value);
5003 for (unsigned i = 0; i < numKids; ++i)
5004 m_out.storePtr(kids[i], result, m_heaps.JSRopeString_fibers[i]);
5005 for (unsigned i = numKids; i < JSRopeString::s_maxInternalRopeLength; ++i)
5006 m_out.storePtr(m_out.intPtrZero, result, m_heaps.JSRopeString_fibers[i]);
5007 LValue flags = m_out.load32(kids[0], m_heaps.JSString_flags);
5008 LValue length = m_out.load32(kids[0], m_heaps.JSString_length);
5009 for (unsigned i = 1; i < numKids; ++i) {
5010 flags = m_out.bitAnd(flags, m_out.load32(kids[i], m_heaps.JSString_flags));
fpizlo@apple.com45e45652016-01-07 21:20:37 +00005011 CheckValue* lengthCheck = m_out.speculateAdd(
fpizlo@apple.coma68bc3a2015-12-21 16:16:01 +00005012 length, m_out.load32(kids[i], m_heaps.JSString_length));
5013 blessSpeculation(lengthCheck, Uncountable, noValue(), nullptr, m_origin);
5014 length = lengthCheck;
msaboff@apple.com95894332014-01-29 19:18:54 +00005015 }
5016 m_out.store32(
5017 m_out.bitAnd(m_out.constInt32(JSString::Is8Bit), flags),
5018 result, m_heaps.JSString_flags);
5019 m_out.store32(length, result, m_heaps.JSString_length);
5020
fpizlo@apple.com101a1682016-11-15 01:49:22 +00005021 mutatorFence();
msaboff@apple.com95894332014-01-29 19:18:54 +00005022 ValueFromBlock fastResult = m_out.anchor(result);
5023 m_out.jump(continuation);
5024
5025 m_out.appendTo(slowPath, continuation);
fpizlo@apple.com6e697962015-10-12 17:56:26 +00005026 LValue slowResultValue;
msaboff@apple.com95894332014-01-29 19:18:54 +00005027 switch (numKids) {
5028 case 2:
fpizlo@apple.com6e697962015-10-12 17:56:26 +00005029 slowResultValue = lazySlowPath(
5030 [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
5031 return createLazyCallGenerator(
5032 operationMakeRope2, locations[0].directGPR(), locations[1].directGPR(),
5033 locations[2].directGPR());
5034 }, kids[0], kids[1]);
msaboff@apple.com95894332014-01-29 19:18:54 +00005035 break;
5036 case 3:
fpizlo@apple.com6e697962015-10-12 17:56:26 +00005037 slowResultValue = lazySlowPath(
5038 [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
5039 return createLazyCallGenerator(
5040 operationMakeRope3, locations[0].directGPR(), locations[1].directGPR(),
5041 locations[2].directGPR(), locations[3].directGPR());
5042 }, kids[0], kids[1], kids[2]);
msaboff@apple.com95894332014-01-29 19:18:54 +00005043 break;
5044 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00005045 DFG_CRASH(m_graph, m_node, "Bad number of children");
5046 break;
msaboff@apple.com95894332014-01-29 19:18:54 +00005047 }
fpizlo@apple.com6e697962015-10-12 17:56:26 +00005048 ValueFromBlock slowResult = m_out.anchor(slowResultValue);
msaboff@apple.com95894332014-01-29 19:18:54 +00005049 m_out.jump(continuation);
5050
5051 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00005052 setJSValue(m_out.phi(Int64, fastResult, slowResult));
msaboff@apple.com95894332014-01-29 19:18:54 +00005053 }
5054
fpizlo@apple.com1d2175a2013-11-06 04:38:23 +00005055 void compileStringCharAt()
5056 {
5057 LValue base = lowCell(m_node->child1());
5058 LValue index = lowInt32(m_node->child2());
5059 LValue storage = lowStorage(m_node->child3());
5060
fpizlo@apple.com91331742016-03-07 02:07:28 +00005061 LBasicBlock fastPath = m_out.newBlock();
5062 LBasicBlock slowPath = m_out.newBlock();
5063 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com1d2175a2013-11-06 04:38:23 +00005064
5065 m_out.branch(
5066 m_out.aboveOrEqual(
msaboff@apple.com95894332014-01-29 19:18:54 +00005067 index, m_out.load32NonNegative(base, m_heaps.JSString_length)),
fpizlo@apple.com975ae502014-02-19 22:29:43 +00005068 rarely(slowPath), usually(fastPath));
fpizlo@apple.com1d2175a2013-11-06 04:38:23 +00005069
5070 LBasicBlock lastNext = m_out.appendTo(fastPath, slowPath);
5071
5072 LValue stringImpl = m_out.loadPtr(base, m_heaps.JSString_value);
5073
fpizlo@apple.com91331742016-03-07 02:07:28 +00005074 LBasicBlock is8Bit = m_out.newBlock();
5075 LBasicBlock is16Bit = m_out.newBlock();
5076 LBasicBlock bitsContinuation = m_out.newBlock();
5077 LBasicBlock bigCharacter = m_out.newBlock();
fpizlo@apple.com1d2175a2013-11-06 04:38:23 +00005078
5079 m_out.branch(
5080 m_out.testIsZero32(
5081 m_out.load32(stringImpl, m_heaps.StringImpl_hashAndFlags),
5082 m_out.constInt32(StringImpl::flagIs8Bit())),
fpizlo@apple.com975ae502014-02-19 22:29:43 +00005083 unsure(is16Bit), unsure(is8Bit));
fpizlo@apple.com1d2175a2013-11-06 04:38:23 +00005084
5085 m_out.appendTo(is8Bit, is16Bit);
5086
benjamin@webkit.org2e864d22015-11-17 06:20:21 +00005087 ValueFromBlock char8Bit = m_out.anchor(
5088 m_out.load8ZeroExt32(m_out.baseIndex(
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00005089 m_heaps.characters8, storage, m_out.zeroExtPtr(index),
benjamin@webkit.org2e864d22015-11-17 06:20:21 +00005090 provenValue(m_node->child2()))));
fpizlo@apple.com1d2175a2013-11-06 04:38:23 +00005091 m_out.jump(bitsContinuation);
5092
5093 m_out.appendTo(is16Bit, bigCharacter);
fpizlo@apple.com373ed6b2015-12-15 04:52:55 +00005094
5095 LValue char16BitValue = m_out.load16ZeroExt32(
5096 m_out.baseIndex(
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00005097 m_heaps.characters16, storage, m_out.zeroExtPtr(index),
fpizlo@apple.com373ed6b2015-12-15 04:52:55 +00005098 provenValue(m_node->child2())));
5099 ValueFromBlock char16Bit = m_out.anchor(char16BitValue);
fpizlo@apple.com975ae502014-02-19 22:29:43 +00005100 m_out.branch(
fpizlo@apple.com373ed6b2015-12-15 04:52:55 +00005101 m_out.aboveOrEqual(char16BitValue, m_out.constInt32(0x100)),
fpizlo@apple.com975ae502014-02-19 22:29:43 +00005102 rarely(bigCharacter), usually(bitsContinuation));
fpizlo@apple.com1d2175a2013-11-06 04:38:23 +00005103
5104 m_out.appendTo(bigCharacter, bitsContinuation);
5105
5106 Vector<ValueFromBlock, 4> results;
5107 results.append(m_out.anchor(vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00005108 Int64, m_out.operation(operationSingleCharacterString),
fpizlo@apple.com373ed6b2015-12-15 04:52:55 +00005109 m_callFrame, char16BitValue)));
fpizlo@apple.com1d2175a2013-11-06 04:38:23 +00005110 m_out.jump(continuation);
5111
5112 m_out.appendTo(bitsContinuation, slowPath);
5113
fpizlo@apple.com994d4532016-07-03 19:34:55 +00005114 LValue character = m_out.phi(Int32, char8Bit, char16Bit);
fpizlo@apple.com1d2175a2013-11-06 04:38:23 +00005115
5116 LValue smallStrings = m_out.constIntPtr(vm().smallStrings.singleCharacterStrings());
5117
5118 results.append(m_out.anchor(m_out.loadPtr(m_out.baseIndex(
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00005119 m_heaps.singleCharacterStrings, smallStrings, m_out.zeroExtPtr(character)))));
fpizlo@apple.com1d2175a2013-11-06 04:38:23 +00005120 m_out.jump(continuation);
5121
5122 m_out.appendTo(slowPath, continuation);
5123
5124 if (m_node->arrayMode().isInBounds()) {
5125 speculate(OutOfBounds, noValue(), 0, m_out.booleanTrue);
5126 results.append(m_out.anchor(m_out.intPtrZero));
5127 } else {
fpizlo@apple.com6793a322014-02-12 05:42:32 +00005128 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
fpizlo@apple.comc2b8c092016-04-24 17:05:51 +00005129
5130 bool prototypeChainIsSane = false;
fpizlo@apple.com1d2175a2013-11-06 04:38:23 +00005131 if (globalObject->stringPrototypeChainIsSane()) {
fpizlo@apple.com141cdcc2015-05-06 23:14:14 +00005132 // FIXME: This could be captured using a Speculation mode that means
5133 // "out-of-bounds loads return a trivial value", something like
5134 // SaneChainOutOfBounds.
5135 // https://bugs.webkit.org/show_bug.cgi?id=144668
5136
5137 m_graph.watchpoints().addLazily(globalObject->stringPrototype()->structure()->transitionWatchpointSet());
5138 m_graph.watchpoints().addLazily(globalObject->objectPrototype()->structure()->transitionWatchpointSet());
5139
fpizlo@apple.comc2b8c092016-04-24 17:05:51 +00005140 prototypeChainIsSane = globalObject->stringPrototypeChainIsSane();
5141 }
5142 if (prototypeChainIsSane) {
fpizlo@apple.com91331742016-03-07 02:07:28 +00005143 LBasicBlock negativeIndex = m_out.newBlock();
fpizlo@apple.com1d2175a2013-11-06 04:38:23 +00005144
5145 results.append(m_out.anchor(m_out.constInt64(JSValue::encode(jsUndefined()))));
fpizlo@apple.com975ae502014-02-19 22:29:43 +00005146 m_out.branch(
5147 m_out.lessThan(index, m_out.int32Zero),
5148 rarely(negativeIndex), usually(continuation));
fpizlo@apple.com1d2175a2013-11-06 04:38:23 +00005149
5150 m_out.appendTo(negativeIndex, continuation);
5151 }
5152
5153 results.append(m_out.anchor(vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00005154 Int64, m_out.operation(operationGetByValStringInt), m_callFrame, base, index)));
fpizlo@apple.com1d2175a2013-11-06 04:38:23 +00005155 }
5156
5157 m_out.jump(continuation);
5158
5159 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00005160 setJSValue(m_out.phi(Int64, results));
fpizlo@apple.com1d2175a2013-11-06 04:38:23 +00005161 }
5162
fpizlo@apple.comfa2eb272013-11-06 16:38:45 +00005163 void compileStringCharCodeAt()
5164 {
fpizlo@apple.com91331742016-03-07 02:07:28 +00005165 LBasicBlock is8Bit = m_out.newBlock();
5166 LBasicBlock is16Bit = m_out.newBlock();
5167 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.comfa2eb272013-11-06 16:38:45 +00005168
5169 LValue base = lowCell(m_node->child1());
5170 LValue index = lowInt32(m_node->child2());
5171 LValue storage = lowStorage(m_node->child3());
5172
5173 speculate(
5174 Uncountable, noValue(), 0,
msaboff@apple.com95894332014-01-29 19:18:54 +00005175 m_out.aboveOrEqual(
5176 index, m_out.load32NonNegative(base, m_heaps.JSString_length)));
fpizlo@apple.comfa2eb272013-11-06 16:38:45 +00005177
5178 LValue stringImpl = m_out.loadPtr(base, m_heaps.JSString_value);
5179
5180 m_out.branch(
5181 m_out.testIsZero32(
5182 m_out.load32(stringImpl, m_heaps.StringImpl_hashAndFlags),
5183 m_out.constInt32(StringImpl::flagIs8Bit())),
fpizlo@apple.com975ae502014-02-19 22:29:43 +00005184 unsure(is16Bit), unsure(is8Bit));
fpizlo@apple.comfa2eb272013-11-06 16:38:45 +00005185
5186 LBasicBlock lastNext = m_out.appendTo(is8Bit, is16Bit);
5187
benjamin@webkit.org2e864d22015-11-17 06:20:21 +00005188 ValueFromBlock char8Bit = m_out.anchor(
5189 m_out.load8ZeroExt32(m_out.baseIndex(
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00005190 m_heaps.characters8, storage, m_out.zeroExtPtr(index),
benjamin@webkit.org2e864d22015-11-17 06:20:21 +00005191 provenValue(m_node->child2()))));
fpizlo@apple.comfa2eb272013-11-06 16:38:45 +00005192 m_out.jump(continuation);
5193
5194 m_out.appendTo(is16Bit, continuation);
5195
benjamin@webkit.org2e864d22015-11-17 06:20:21 +00005196 ValueFromBlock char16Bit = m_out.anchor(
5197 m_out.load16ZeroExt32(m_out.baseIndex(
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00005198 m_heaps.characters16, storage, m_out.zeroExtPtr(index),
benjamin@webkit.org2e864d22015-11-17 06:20:21 +00005199 provenValue(m_node->child2()))));
fpizlo@apple.comfa2eb272013-11-06 16:38:45 +00005200 m_out.jump(continuation);
5201
5202 m_out.appendTo(continuation, lastNext);
5203
fpizlo@apple.com994d4532016-07-03 19:34:55 +00005204 setInt32(m_out.phi(Int32, char8Bit, char16Bit));
fpizlo@apple.comfa2eb272013-11-06 16:38:45 +00005205 }
fpizlo@apple.com47c16d72016-02-16 19:12:36 +00005206
5207 void compileStringFromCharCode()
5208 {
5209 Edge childEdge = m_node->child1();
5210
5211 if (childEdge.useKind() == UntypedUse) {
5212 LValue result = vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00005213 Int64, m_out.operation(operationStringFromCharCodeUntyped), m_callFrame,
fpizlo@apple.com47c16d72016-02-16 19:12:36 +00005214 lowJSValue(childEdge));
5215 setJSValue(result);
5216 return;
5217 }
5218
5219 DFG_ASSERT(m_graph, m_node, childEdge.useKind() == Int32Use);
5220
5221 LValue value = lowInt32(childEdge);
5222
fpizlo@apple.com91331742016-03-07 02:07:28 +00005223 LBasicBlock smallIntCase = m_out.newBlock();
5224 LBasicBlock slowCase = m_out.newBlock();
5225 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com47c16d72016-02-16 19:12:36 +00005226
5227 m_out.branch(
5228 m_out.aboveOrEqual(value, m_out.constInt32(0xff)),
5229 rarely(slowCase), usually(smallIntCase));
5230
5231 LBasicBlock lastNext = m_out.appendTo(smallIntCase, slowCase);
5232
5233 LValue smallStrings = m_out.constIntPtr(vm().smallStrings.singleCharacterStrings());
5234 LValue fastResultValue = m_out.loadPtr(
5235 m_out.baseIndex(m_heaps.singleCharacterStrings, smallStrings, m_out.zeroExtPtr(value)));
5236 ValueFromBlock fastResult = m_out.anchor(fastResultValue);
5237 m_out.jump(continuation);
5238
5239 m_out.appendTo(slowCase, continuation);
5240
5241 LValue slowResultValue = vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00005242 pointerType(), m_out.operation(operationStringFromCharCode), m_callFrame, value);
fpizlo@apple.com47c16d72016-02-16 19:12:36 +00005243 ValueFromBlock slowResult = m_out.anchor(slowResultValue);
5244 m_out.jump(continuation);
5245
5246 m_out.appendTo(continuation, lastNext);
5247
fpizlo@apple.com994d4532016-07-03 19:34:55 +00005248 setJSValue(m_out.phi(Int64, fastResult, slowResult));
fpizlo@apple.com47c16d72016-02-16 19:12:36 +00005249 }
fpizlo@apple.comfa2eb272013-11-06 16:38:45 +00005250
oliver@apple.comea771492013-07-25 03:58:38 +00005251 void compileGetByOffset()
5252 {
fpizlo@apple.com9800ede2014-09-20 17:59:58 +00005253 StorageAccessData& data = m_node->storageAccessData();
oliver@apple.comea771492013-07-25 03:58:38 +00005254
fpizlo@apple.com43219522014-02-25 02:02:50 +00005255 setJSValue(loadProperty(
5256 lowStorage(m_node->child1()), data.identifierNumber, data.offset));
oliver@apple.comea771492013-07-25 03:58:38 +00005257 }
5258
fpizlo@apple.com4c6b8ad2014-07-22 21:08:50 +00005259 void compileGetGetter()
5260 {
5261 setJSValue(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.GetterSetter_getter));
5262 }
5263
5264 void compileGetSetter()
5265 {
5266 setJSValue(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.GetterSetter_setter));
5267 }
5268
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00005269 void compileMultiGetByOffset()
5270 {
5271 LValue base = lowCell(m_node->child1());
5272
5273 MultiGetByOffsetData& data = m_node->multiGetByOffsetData();
fpizlo@apple.com3378c482014-07-27 23:14:40 +00005274
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +00005275 if (data.cases.isEmpty()) {
fpizlo@apple.com3ce6ab62016-02-18 16:40:25 +00005276 // Protect against creating a Phi function with zero inputs. LLVM didn't like that.
5277 // It's not clear if this is needed anymore.
5278 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=154382
fpizlo@apple.com3378c482014-07-27 23:14:40 +00005279 terminate(BadCache);
5280 return;
5281 }
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00005282
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +00005283 Vector<LBasicBlock, 2> blocks(data.cases.size());
5284 for (unsigned i = data.cases.size(); i--;)
fpizlo@apple.com91331742016-03-07 02:07:28 +00005285 blocks[i] = m_out.newBlock();
5286 LBasicBlock exit = m_out.newBlock();
5287 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00005288
5289 Vector<SwitchCase, 2> cases;
sbarati@apple.com239d20b2017-01-26 23:50:58 +00005290 RegisteredStructureSet baseSet;
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +00005291 for (unsigned i = data.cases.size(); i--;) {
5292 MultiGetByOffsetCase getCase = data.cases[i];
5293 for (unsigned j = getCase.set().size(); j--;) {
sbarati@apple.com239d20b2017-01-26 23:50:58 +00005294 RegisteredStructure structure = getCase.set()[j];
fpizlo@apple.comaa055802015-05-30 21:48:35 +00005295 baseSet.add(structure);
5296 cases.append(SwitchCase(weakStructureID(structure), blocks[i], Weight(1)));
fpizlo@apple.com975ae502014-02-19 22:29:43 +00005297 }
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00005298 }
fpizlo@apple.com975ae502014-02-19 22:29:43 +00005299 m_out.switchInstruction(
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +00005300 m_out.load32(base, m_heaps.JSCell_structureID), cases, exit, Weight(0));
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00005301
5302 LBasicBlock lastNext = m_out.m_nextBlock;
5303
5304 Vector<ValueFromBlock, 2> results;
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +00005305 for (unsigned i = data.cases.size(); i--;) {
5306 MultiGetByOffsetCase getCase = data.cases[i];
5307 GetByOffsetMethod method = getCase.method();
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00005308
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +00005309 m_out.appendTo(blocks[i], i + 1 < data.cases.size() ? blocks[i + 1] : exit);
5310
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00005311 LValue result;
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +00005312
5313 switch (method.kind()) {
5314 case GetByOffsetMethod::Invalid:
5315 RELEASE_ASSERT_NOT_REACHED();
5316 break;
5317
5318 case GetByOffsetMethod::Constant:
5319 result = m_out.constInt64(JSValue::encode(method.constant()->value()));
5320 break;
5321
5322 case GetByOffsetMethod::Load:
5323 case GetByOffsetMethod::LoadFromPrototype: {
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00005324 LValue propertyBase;
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +00005325 if (method.kind() == GetByOffsetMethod::Load)
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00005326 propertyBase = base;
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +00005327 else
5328 propertyBase = weakPointer(method.prototype()->value().asCell());
5329 if (!isInlineOffset(method.offset()))
fpizlo@apple.com95ef6492016-03-15 15:26:36 +00005330 propertyBase = m_out.loadPtr(propertyBase, m_heaps.JSObject_butterfly);
fpizlo@apple.com6b62eaf2015-08-03 23:13:56 +00005331 result = loadProperty(
5332 propertyBase, data.identifierNumber, method.offset());
5333 break;
5334 } }
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00005335
5336 results.append(m_out.anchor(result));
5337 m_out.jump(continuation);
5338 }
5339
5340 m_out.appendTo(exit, continuation);
fpizlo@apple.comaa055802015-05-30 21:48:35 +00005341 if (!m_interpreter.forNode(m_node->child1()).m_structure.isSubsetOf(baseSet))
5342 speculate(BadCache, noValue(), nullptr, m_out.booleanTrue);
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00005343 m_out.unreachable();
5344
5345 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00005346 setJSValue(m_out.phi(Int64, results));
fpizlo@apple.com51614cc2014-02-17 06:35:32 +00005347 }
5348
oliver@apple.comea771492013-07-25 03:58:38 +00005349 void compilePutByOffset()
5350 {
fpizlo@apple.com9800ede2014-09-20 17:59:58 +00005351 StorageAccessData& data = m_node->storageAccessData();
oliver@apple.comea771492013-07-25 03:58:38 +00005352
fpizlo@apple.com43219522014-02-25 02:02:50 +00005353 storeProperty(
oliver@apple.comea771492013-07-25 03:58:38 +00005354 lowJSValue(m_node->child3()),
fpizlo@apple.com43219522014-02-25 02:02:50 +00005355 lowStorage(m_node->child1()), data.identifierNumber, data.offset);
5356 }
5357
5358 void compileMultiPutByOffset()
5359 {
5360 LValue base = lowCell(m_node->child1());
5361 LValue value = lowJSValue(m_node->child2());
5362
5363 MultiPutByOffsetData& data = m_node->multiPutByOffsetData();
5364
5365 Vector<LBasicBlock, 2> blocks(data.variants.size());
5366 for (unsigned i = data.variants.size(); i--;)
fpizlo@apple.com91331742016-03-07 02:07:28 +00005367 blocks[i] = m_out.newBlock();
5368 LBasicBlock exit = m_out.newBlock();
5369 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com43219522014-02-25 02:02:50 +00005370
5371 Vector<SwitchCase, 2> cases;
sbarati@apple.com239d20b2017-01-26 23:50:58 +00005372 RegisteredStructureSet baseSet;
fpizlo@apple.com43219522014-02-25 02:02:50 +00005373 for (unsigned i = data.variants.size(); i--;) {
5374 PutByIdVariant variant = data.variants[i];
fpizlo@apple.com3378c482014-07-27 23:14:40 +00005375 for (unsigned j = variant.oldStructure().size(); j--;) {
sbarati@apple.com239d20b2017-01-26 23:50:58 +00005376 RegisteredStructure structure = m_graph.registerStructure(variant.oldStructure()[j]);
fpizlo@apple.comaa055802015-05-30 21:48:35 +00005377 baseSet.add(structure);
5378 cases.append(SwitchCase(weakStructureID(structure), blocks[i], Weight(1)));
fpizlo@apple.com3378c482014-07-27 23:14:40 +00005379 }
fpizlo@apple.com43219522014-02-25 02:02:50 +00005380 }
5381 m_out.switchInstruction(
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +00005382 m_out.load32(base, m_heaps.JSCell_structureID), cases, exit, Weight(0));
fpizlo@apple.com43219522014-02-25 02:02:50 +00005383
5384 LBasicBlock lastNext = m_out.m_nextBlock;
5385
5386 for (unsigned i = data.variants.size(); i--;) {
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00005387 m_out.appendTo(blocks[i], i + 1 < data.variants.size() ? blocks[i + 1] : exit);
fpizlo@apple.com43219522014-02-25 02:02:50 +00005388
5389 PutByIdVariant variant = data.variants[i];
fpizlo@apple.com12835772015-09-21 20:49:04 +00005390
5391 checkInferredType(m_node->child2(), value, variant.requiredType());
fpizlo@apple.com43219522014-02-25 02:02:50 +00005392
5393 LValue storage;
5394 if (variant.kind() == PutByIdVariant::Replace) {
5395 if (isInlineOffset(variant.offset()))
5396 storage = base;
5397 else
fpizlo@apple.com95ef6492016-03-15 15:26:36 +00005398 storage = m_out.loadPtr(base, m_heaps.JSObject_butterfly);
fpizlo@apple.com43219522014-02-25 02:02:50 +00005399 } else {
fpizlo@apple.com101a1682016-11-15 01:49:22 +00005400 DFG_ASSERT(m_graph, m_node, variant.kind() == PutByIdVariant::Transition);
fpizlo@apple.com43219522014-02-25 02:02:50 +00005401 m_graph.m_plan.transitions.addLazily(
5402 codeBlock(), m_node->origin.semantic.codeOriginOwner(),
fpizlo@apple.com3378c482014-07-27 23:14:40 +00005403 variant.oldStructureForTransition(), variant.newStructure());
fpizlo@apple.com43219522014-02-25 02:02:50 +00005404
5405 storage = storageForTransition(
fpizlo@apple.com3378c482014-07-27 23:14:40 +00005406 base, variant.offset(),
5407 variant.oldStructureForTransition(), variant.newStructure());
fpizlo@apple.com101a1682016-11-15 01:49:22 +00005408 }
5409
5410 storeProperty(value, storage, data.identifierNumber, variant.offset());
5411
5412 if (variant.kind() == PutByIdVariant::Transition) {
fpizlo@apple.com3378c482014-07-27 23:14:40 +00005413 ASSERT(variant.oldStructureForTransition()->indexingType() == variant.newStructure()->indexingType());
5414 ASSERT(variant.oldStructureForTransition()->typeInfo().inlineTypeFlags() == variant.newStructure()->typeInfo().inlineTypeFlags());
5415 ASSERT(variant.oldStructureForTransition()->typeInfo().type() == variant.newStructure()->typeInfo().type());
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +00005416 m_out.store32(
sbarati@apple.com239d20b2017-01-26 23:50:58 +00005417 weakStructureID(m_graph.registerStructure(variant.newStructure())), base, m_heaps.JSCell_structureID);
fpizlo@apple.com43219522014-02-25 02:02:50 +00005418 }
5419
fpizlo@apple.com43219522014-02-25 02:02:50 +00005420 m_out.jump(continuation);
5421 }
5422
5423 m_out.appendTo(exit, continuation);
fpizlo@apple.comaa055802015-05-30 21:48:35 +00005424 if (!m_interpreter.forNode(m_node->child1()).m_structure.isSubsetOf(baseSet))
5425 speculate(BadCache, noValue(), nullptr, m_out.booleanTrue);
fpizlo@apple.com43219522014-02-25 02:02:50 +00005426 m_out.unreachable();
5427
5428 m_out.appendTo(continuation, lastNext);
oliver@apple.comea771492013-07-25 03:58:38 +00005429 }
5430
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00005431 void compileGetGlobalVariable()
oliver@apple.comea771492013-07-25 03:58:38 +00005432 {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00005433 setJSValue(m_out.load64(m_out.absolute(m_node->variablePointer())));
oliver@apple.comea771492013-07-25 03:58:38 +00005434 }
5435
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00005436 void compilePutGlobalVariable()
oliver@apple.comea771492013-07-25 03:58:38 +00005437 {
5438 m_out.store64(
fpizlo@apple.com33ea5ee2015-05-15 03:51:52 +00005439 lowJSValue(m_node->child2()), m_out.absolute(m_node->variablePointer()));
oliver@apple.comea771492013-07-25 03:58:38 +00005440 }
5441
fpizlo@apple.com86468342013-11-27 02:47:43 +00005442 void compileNotifyWrite()
fpizlo@apple.com33961712013-11-20 05:49:05 +00005443 {
fpizlo@apple.com3a2fa4c2015-04-13 22:13:12 +00005444 WatchpointSet* set = m_node->watchpointSet();
fpizlo@apple.com86468342013-11-27 02:47:43 +00005445
fpizlo@apple.com91331742016-03-07 02:07:28 +00005446 LBasicBlock isNotInvalidated = m_out.newBlock();
5447 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com33961712013-11-20 05:49:05 +00005448
benjamin@webkit.org2e864d22015-11-17 06:20:21 +00005449 LValue state = m_out.load8ZeroExt32(m_out.absolute(set->addressOfState()));
fpizlo@apple.com33961712013-11-20 05:49:05 +00005450 m_out.branch(
benjamin@webkit.org2e864d22015-11-17 06:20:21 +00005451 m_out.equal(state, m_out.constInt32(IsInvalidated)),
fpizlo@apple.com975ae502014-02-19 22:29:43 +00005452 usually(continuation), rarely(isNotInvalidated));
fpizlo@apple.com33961712013-11-20 05:49:05 +00005453
fpizlo@apple.com3a2fa4c2015-04-13 22:13:12 +00005454 LBasicBlock lastNext = m_out.appendTo(isNotInvalidated, continuation);
fpizlo@apple.com33961712013-11-20 05:49:05 +00005455
fpizlo@apple.com6e697962015-10-12 17:56:26 +00005456 lazySlowPath(
5457 [=] (const Vector<Location>&) -> RefPtr<LazySlowPath::Generator> {
5458 return createLazyCallGenerator(
5459 operationNotifyWrite, InvalidGPRReg, CCallHelpers::TrustedImmPtr(set));
5460 });
fpizlo@apple.com33961712013-11-20 05:49:05 +00005461 m_out.jump(continuation);
5462
5463 m_out.appendTo(continuation, lastNext);
5464 }
5465
msaboff@apple.com95894332014-01-29 19:18:54 +00005466 void compileGetCallee()
5467 {
mark.lam@apple.com2bd89342016-07-08 22:58:15 +00005468 setJSValue(m_out.loadPtr(addressFor(CallFrameSlot::callee)));
msaboff@apple.com95894332014-01-29 19:18:54 +00005469 }
5470
keith_miller@apple.com85aeabb2016-06-03 23:06:39 +00005471 void compileGetArgumentCountIncludingThis()
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00005472 {
mark.lam@apple.com2bd89342016-07-08 22:58:15 +00005473 setInt32(m_out.load32(payloadFor(CallFrameSlot::argumentCount)));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00005474 }
5475
msaboff@apple.com95894332014-01-29 19:18:54 +00005476 void compileGetScope()
5477 {
5478 setJSValue(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSFunction_scope));
5479 }
5480
fpizlo@apple.com0d5b2e82013-09-08 03:24:13 +00005481 void compileSkipScope()
5482 {
5483 setJSValue(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSScope_next));
5484 }
fpizlo@apple.com7518ba22016-03-06 20:11:09 +00005485
5486 void compileGetGlobalObject()
5487 {
5488 LValue structure = loadStructure(lowCell(m_node->child1()));
5489 setJSValue(m_out.loadPtr(structure, m_heaps.Structure_globalObject));
5490 }
fpizlo@apple.com0d5b2e82013-09-08 03:24:13 +00005491
fpizlo@apple.com0d5b2e82013-09-08 03:24:13 +00005492 void compileGetClosureVar()
5493 {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00005494 setJSValue(
5495 m_out.load64(
5496 lowCell(m_node->child1()),
5497 m_heaps.JSEnvironmentRecord_variables[m_node->scopeOffset().offset()]));
fpizlo@apple.com0d5b2e82013-09-08 03:24:13 +00005498 }
5499
5500 void compilePutClosureVar()
5501 {
5502 m_out.store64(
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00005503 lowJSValue(m_node->child2()),
5504 lowCell(m_node->child1()),
5505 m_heaps.JSEnvironmentRecord_variables[m_node->scopeOffset().offset()]);
5506 }
5507
5508 void compileGetFromArguments()
5509 {
5510 setJSValue(
5511 m_out.load64(
5512 lowCell(m_node->child1()),
5513 m_heaps.DirectArguments_storage[m_node->capturedArgumentsOffset().offset()]));
5514 }
5515
5516 void compilePutToArguments()
5517 {
5518 m_out.store64(
5519 lowJSValue(m_node->child2()),
5520 lowCell(m_node->child1()),
5521 m_heaps.DirectArguments_storage[m_node->capturedArgumentsOffset().offset()]);
fpizlo@apple.com0d5b2e82013-09-08 03:24:13 +00005522 }
utatane.tea@gmail.combebf7852016-11-10 06:34:05 +00005523
5524 void compileGetArgument()
5525 {
5526 LValue argumentCount = m_out.load32(payloadFor(AssemblyHelpers::argumentCount(m_node->origin.semantic)));
5527
5528 LBasicBlock inBounds = m_out.newBlock();
5529 LBasicBlock outOfBounds = m_out.newBlock();
5530 LBasicBlock continuation = m_out.newBlock();
5531
5532 m_out.branch(m_out.lessThanOrEqual(argumentCount, m_out.constInt32(m_node->argumentIndex())), unsure(outOfBounds), unsure(inBounds));
5533
5534 LBasicBlock lastNext = m_out.appendTo(inBounds, outOfBounds);
5535 VirtualRegister arg = AssemblyHelpers::argumentsStart(m_node->origin.semantic) + m_node->argumentIndex() - 1;
5536 ValueFromBlock inBoundsResult = m_out.anchor(m_out.load64(addressFor(arg)));
5537 m_out.jump(continuation);
5538
5539 m_out.appendTo(outOfBounds, continuation);
5540 ValueFromBlock outOfBoundsResult = m_out.anchor(m_out.constInt64(ValueUndefined));
5541 m_out.jump(continuation);
5542
5543 m_out.appendTo(continuation, lastNext);
5544 setJSValue(m_out.phi(Int64, inBoundsResult, outOfBoundsResult));
5545 }
fpizlo@apple.com0d5b2e82013-09-08 03:24:13 +00005546
oliver@apple.comea771492013-07-25 03:58:38 +00005547 void compileCompareEq()
5548 {
oliver@apple.com023d1c72013-07-25 03:59:57 +00005549 if (m_node->isBinaryUseKind(Int32Use)
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00005550 || m_node->isBinaryUseKind(Int52RepUse)
5551 || m_node->isBinaryUseKind(DoubleRepUse)
fpizlo@apple.come079bb52014-03-05 07:41:03 +00005552 || m_node->isBinaryUseKind(ObjectUse)
fpizlo@apple.com385a33a2014-03-18 20:53:07 +00005553 || m_node->isBinaryUseKind(BooleanUse)
utatane.tea@gmail.com382ef652015-10-01 17:20:44 +00005554 || m_node->isBinaryUseKind(SymbolUse)
fpizlo@apple.com2d17ae02016-02-17 05:29:34 +00005555 || m_node->isBinaryUseKind(StringIdentUse)
5556 || m_node->isBinaryUseKind(StringUse)) {
oliver@apple.com023d1c72013-07-25 03:59:57 +00005557 compileCompareStrictEq();
5558 return;
5559 }
5560
fpizlo@apple.com312efcd2014-03-10 22:11:35 +00005561 if (m_node->isBinaryUseKind(ObjectUse, ObjectOrOtherUse)) {
fpizlo@apple.com76e5b2792014-02-11 20:28:59 +00005562 compareEqObjectOrOtherToObject(m_node->child2(), m_node->child1());
5563 return;
5564 }
5565
fpizlo@apple.com312efcd2014-03-10 22:11:35 +00005566 if (m_node->isBinaryUseKind(ObjectOrOtherUse, ObjectUse)) {
fpizlo@apple.com8a4e4dd2014-02-12 04:24:37 +00005567 compareEqObjectOrOtherToObject(m_node->child1(), m_node->child2());
fpizlo@apple.com76e5b2792014-02-11 20:28:59 +00005568 return;
5569 }
benjamin@webkit.org32b8d0a2015-08-19 04:09:12 +00005570
5571 if (m_node->child1().useKind() == OtherUse) {
5572 ASSERT(!m_interpreter.needsTypeCheck(m_node->child1(), SpecOther));
5573 setBoolean(equalNullOrUndefined(m_node->child2(), AllCellsAreFalse, EqualNullOrUndefined, ManualOperandSpeculation));
5574 return;
5575 }
5576
5577 if (m_node->child2().useKind() == OtherUse) {
5578 ASSERT(!m_interpreter.needsTypeCheck(m_node->child2(), SpecOther));
5579 setBoolean(equalNullOrUndefined(m_node->child1(), AllCellsAreFalse, EqualNullOrUndefined, ManualOperandSpeculation));
5580 return;
5581 }
5582
commit-queue@webkit.org0ee8ee92016-08-30 01:48:10 +00005583 DFG_ASSERT(m_graph, m_node, m_node->isBinaryUseKind(UntypedUse));
5584 nonSpeculativeCompare(
5585 [&] (LValue left, LValue right) {
5586 return m_out.equal(left, right);
5587 },
5588 operationCompareEq);
oliver@apple.com023d1c72013-07-25 03:59:57 +00005589 }
5590
5591 void compileCompareStrictEq()
5592 {
oliver@apple.comea771492013-07-25 03:58:38 +00005593 if (m_node->isBinaryUseKind(Int32Use)) {
oliver@apple.com827d2cf2013-07-25 04:04:45 +00005594 setBoolean(
oliver@apple.comea771492013-07-25 03:58:38 +00005595 m_out.equal(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
5596 return;
5597 }
5598
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00005599 if (m_node->isBinaryUseKind(Int52RepUse)) {
fpizlo@apple.com6921b292013-09-18 17:14:02 +00005600 Int52Kind kind;
5601 LValue left = lowWhicheverInt52(m_node->child1(), kind);
5602 LValue right = lowInt52(m_node->child2(), kind);
5603 setBoolean(m_out.equal(left, right));
5604 return;
5605 }
5606
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00005607 if (m_node->isBinaryUseKind(DoubleRepUse)) {
oliver@apple.com827d2cf2013-07-25 04:04:45 +00005608 setBoolean(
oliver@apple.com32295c12013-07-25 03:59:06 +00005609 m_out.doubleEqual(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
fpizlo@apple.comfa258dc2013-09-07 05:47:57 +00005610 return;
oliver@apple.com32295c12013-07-25 03:59:06 +00005611 }
5612
fpizlo@apple.com385a33a2014-03-18 20:53:07 +00005613 if (m_node->isBinaryUseKind(StringIdentUse)) {
5614 setBoolean(
5615 m_out.equal(lowStringIdent(m_node->child1()), lowStringIdent(m_node->child2())));
5616 return;
5617 }
commit-queue@webkit.org902685c2015-06-24 19:13:54 +00005618
fpizlo@apple.com2d17ae02016-02-17 05:29:34 +00005619 if (m_node->isBinaryUseKind(StringUse)) {
5620 LValue left = lowCell(m_node->child1());
5621 LValue right = lowCell(m_node->child2());
5622
fpizlo@apple.com91331742016-03-07 02:07:28 +00005623 LBasicBlock notTriviallyEqualCase = m_out.newBlock();
5624 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com2d17ae02016-02-17 05:29:34 +00005625
5626 speculateString(m_node->child1(), left);
5627
5628 ValueFromBlock fastResult = m_out.anchor(m_out.booleanTrue);
5629 m_out.branch(
5630 m_out.equal(left, right), unsure(continuation), unsure(notTriviallyEqualCase));
5631
5632 LBasicBlock lastNext = m_out.appendTo(notTriviallyEqualCase, continuation);
5633
5634 speculateString(m_node->child2(), right);
5635
5636 ValueFromBlock slowResult = m_out.anchor(stringsEqual(left, right));
5637 m_out.jump(continuation);
5638
5639 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00005640 setBoolean(m_out.phi(Int32, fastResult, slowResult));
fpizlo@apple.com2d17ae02016-02-17 05:29:34 +00005641 return;
5642 }
5643
commit-queue@webkit.org902685c2015-06-24 19:13:54 +00005644 if (m_node->isBinaryUseKind(ObjectUse, UntypedUse)) {
5645 setBoolean(
5646 m_out.equal(
5647 lowNonNullObject(m_node->child1()),
5648 lowJSValue(m_node->child2())));
5649 return;
5650 }
fpizlo@apple.com385a33a2014-03-18 20:53:07 +00005651
commit-queue@webkit.org902685c2015-06-24 19:13:54 +00005652 if (m_node->isBinaryUseKind(UntypedUse, ObjectUse)) {
5653 setBoolean(
5654 m_out.equal(
5655 lowNonNullObject(m_node->child2()),
5656 lowJSValue(m_node->child1())));
5657 return;
5658 }
5659
oliver@apple.comea771492013-07-25 03:58:38 +00005660 if (m_node->isBinaryUseKind(ObjectUse)) {
oliver@apple.com827d2cf2013-07-25 04:04:45 +00005661 setBoolean(
oliver@apple.com410b5412013-07-25 03:59:47 +00005662 m_out.equal(
5663 lowNonNullObject(m_node->child1()),
5664 lowNonNullObject(m_node->child2())));
oliver@apple.comea771492013-07-25 03:58:38 +00005665 return;
5666 }
5667
fpizlo@apple.come079bb52014-03-05 07:41:03 +00005668 if (m_node->isBinaryUseKind(BooleanUse)) {
5669 setBoolean(
5670 m_out.equal(lowBoolean(m_node->child1()), lowBoolean(m_node->child2())));
5671 return;
5672 }
utatane.tea@gmail.com382ef652015-10-01 17:20:44 +00005673
5674 if (m_node->isBinaryUseKind(SymbolUse)) {
utatane.tea@gmail.com7f364f22016-07-29 07:15:01 +00005675 LValue leftSymbol = lowSymbol(m_node->child1());
5676 LValue rightSymbol = lowSymbol(m_node->child2());
5677 setBoolean(m_out.equal(leftSymbol, rightSymbol));
utatane.tea@gmail.com382ef652015-10-01 17:20:44 +00005678 return;
5679 }
fpizlo@apple.come079bb52014-03-05 07:41:03 +00005680
fpizlo@apple.comcef76b22016-07-21 06:23:10 +00005681 if (m_node->isBinaryUseKind(SymbolUse, UntypedUse)
5682 || m_node->isBinaryUseKind(UntypedUse, SymbolUse)) {
5683 Edge symbolEdge = m_node->child1();
5684 Edge untypedEdge = m_node->child2();
5685 if (symbolEdge.useKind() != SymbolUse)
5686 std::swap(symbolEdge, untypedEdge);
5687
utatane.tea@gmail.com7f364f22016-07-29 07:15:01 +00005688 LValue leftSymbol = lowSymbol(symbolEdge);
fpizlo@apple.comcef76b22016-07-21 06:23:10 +00005689 LValue untypedValue = lowJSValue(untypedEdge);
utatane.tea@gmail.com7f364f22016-07-29 07:15:01 +00005690
5691 setBoolean(m_out.equal(leftSymbol, untypedValue));
fpizlo@apple.comcef76b22016-07-21 06:23:10 +00005692 return;
5693 }
5694
fpizlo@apple.com312efcd2014-03-10 22:11:35 +00005695 if (m_node->isBinaryUseKind(MiscUse, UntypedUse)
5696 || m_node->isBinaryUseKind(UntypedUse, MiscUse)) {
5697 speculate(m_node->child1());
5698 speculate(m_node->child2());
fpizlo@apple.come079bb52014-03-05 07:41:03 +00005699 LValue left = lowJSValue(m_node->child1(), ManualOperandSpeculation);
5700 LValue right = lowJSValue(m_node->child2(), ManualOperandSpeculation);
fpizlo@apple.come079bb52014-03-05 07:41:03 +00005701 setBoolean(m_out.equal(left, right));
5702 return;
5703 }
5704
fpizlo@apple.com385a33a2014-03-18 20:53:07 +00005705 if (m_node->isBinaryUseKind(StringIdentUse, NotStringVarUse)
5706 || m_node->isBinaryUseKind(NotStringVarUse, StringIdentUse)) {
5707 Edge leftEdge = m_node->childFor(StringIdentUse);
5708 Edge rightEdge = m_node->childFor(NotStringVarUse);
5709
5710 LValue left = lowStringIdent(leftEdge);
5711 LValue rightValue = lowJSValue(rightEdge, ManualOperandSpeculation);
5712
fpizlo@apple.com91331742016-03-07 02:07:28 +00005713 LBasicBlock isCellCase = m_out.newBlock();
5714 LBasicBlock isStringCase = m_out.newBlock();
5715 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com385a33a2014-03-18 20:53:07 +00005716
5717 ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse);
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00005718 m_out.branch(
5719 isCell(rightValue, provenType(rightEdge)),
5720 unsure(isCellCase), unsure(continuation));
fpizlo@apple.com385a33a2014-03-18 20:53:07 +00005721
5722 LBasicBlock lastNext = m_out.appendTo(isCellCase, isStringCase);
5723 ValueFromBlock notStringResult = m_out.anchor(m_out.booleanFalse);
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00005724 m_out.branch(
5725 isString(rightValue, provenType(rightEdge)),
5726 unsure(isStringCase), unsure(continuation));
fpizlo@apple.com385a33a2014-03-18 20:53:07 +00005727
5728 m_out.appendTo(isStringCase, continuation);
5729 LValue right = m_out.loadPtr(rightValue, m_heaps.JSString_value);
5730 speculateStringIdent(rightEdge, rightValue, right);
5731 ValueFromBlock isStringResult = m_out.anchor(m_out.equal(left, right));
5732 m_out.jump(continuation);
5733
5734 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00005735 setBoolean(m_out.phi(Int32, notCellResult, notStringResult, isStringResult));
fpizlo@apple.com385a33a2014-03-18 20:53:07 +00005736 return;
5737 }
benjamin@webkit.org977a05b2016-08-27 00:36:15 +00005738
5739 if (m_node->isBinaryUseKind(StringUse, UntypedUse)) {
5740 compileStringToUntypedStrictEquality(m_node->child1(), m_node->child2());
5741 return;
5742 }
5743 if (m_node->isBinaryUseKind(UntypedUse, StringUse)) {
5744 compileStringToUntypedStrictEquality(m_node->child2(), m_node->child1());
5745 return;
5746 }
5747
5748 DFG_ASSERT(m_graph, m_node, m_node->isBinaryUseKind(UntypedUse));
5749 nonSpeculativeCompare(
5750 [&] (LValue left, LValue right) {
5751 return m_out.equal(left, right);
5752 },
5753 operationCompareStrictEq);
oliver@apple.comea771492013-07-25 03:58:38 +00005754 }
benjamin@webkit.org977a05b2016-08-27 00:36:15 +00005755
5756 void compileStringToUntypedStrictEquality(Edge stringEdge, Edge untypedEdge)
5757 {
5758 ASSERT(stringEdge.useKind() == StringUse);
5759 ASSERT(untypedEdge.useKind() == UntypedUse);
5760
5761 LValue leftString = lowCell(stringEdge);
5762 LValue rightValue = lowJSValue(untypedEdge);
5763 SpeculatedType rightValueType = provenType(untypedEdge);
5764
5765 // Verify left is string.
5766 speculateString(stringEdge, leftString);
5767
5768 LBasicBlock testUntypedEdgeIsCell = m_out.newBlock();
5769 LBasicBlock testUntypedEdgeIsString = m_out.newBlock();
5770 LBasicBlock testStringEquality = m_out.newBlock();
5771 LBasicBlock continuation = m_out.newBlock();
5772
5773 // Given left is string. If the value are strictly equal, rightValue has to be the same string.
5774 ValueFromBlock fastTrue = m_out.anchor(m_out.booleanTrue);
5775 m_out.branch(m_out.equal(leftString, rightValue), unsure(continuation), unsure(testUntypedEdgeIsCell));
5776
5777 LBasicBlock lastNext = m_out.appendTo(testUntypedEdgeIsCell, testUntypedEdgeIsString);
5778 ValueFromBlock fastFalse = m_out.anchor(m_out.booleanFalse);
5779 m_out.branch(isNotCell(rightValue, rightValueType), unsure(continuation), unsure(testUntypedEdgeIsString));
5780
5781 // Check if the untyped edge is a string.
5782 m_out.appendTo(testUntypedEdgeIsString, testStringEquality);
5783 m_out.branch(isNotString(rightValue, rightValueType), unsure(continuation), unsure(testStringEquality));
5784
5785 // Full String compare.
5786 m_out.appendTo(testStringEquality, continuation);
5787 ValueFromBlock slowResult = m_out.anchor(stringsEqual(leftString, rightValue));
5788 m_out.jump(continuation);
5789
5790 // Continuation.
5791 m_out.appendTo(continuation, lastNext);
5792 setBoolean(m_out.phi(Int32, fastTrue, fastFalse, slowResult));
5793 }
5794
fpizlo@apple.com4077f612016-07-18 19:12:57 +00005795 void compileCompareEqPtr()
oliver@apple.com9a58da12013-07-25 04:00:00 +00005796 {
oliver@apple.com827d2cf2013-07-25 04:04:45 +00005797 setBoolean(
oliver@apple.com9a58da12013-07-25 04:00:00 +00005798 m_out.equal(
5799 lowJSValue(m_node->child1()),
fpizlo@apple.com4077f612016-07-18 19:12:57 +00005800 weakPointer(m_node->cellOperand()->cell())));
oliver@apple.com9a58da12013-07-25 04:00:00 +00005801 }
5802
oliver@apple.comea771492013-07-25 03:58:38 +00005803 void compileCompareLess()
5804 {
fpizlo@apple.com12a3fbd2015-11-19 22:18:15 +00005805 compare(
5806 [&] (LValue left, LValue right) {
5807 return m_out.lessThan(left, right);
5808 },
5809 [&] (LValue left, LValue right) {
5810 return m_out.doubleLessThan(left, right);
5811 },
commit-queue@webkit.org36c52882016-04-22 05:08:28 +00005812 operationCompareStringImplLess,
5813 operationCompareStringLess,
fpizlo@apple.com12a3fbd2015-11-19 22:18:15 +00005814 operationCompareLess);
oliver@apple.com1f9b9b72013-07-25 03:59:52 +00005815 }
5816
5817 void compileCompareLessEq()
5818 {
fpizlo@apple.com12a3fbd2015-11-19 22:18:15 +00005819 compare(
5820 [&] (LValue left, LValue right) {
5821 return m_out.lessThanOrEqual(left, right);
5822 },
5823 [&] (LValue left, LValue right) {
5824 return m_out.doubleLessThanOrEqual(left, right);
5825 },
commit-queue@webkit.org36c52882016-04-22 05:08:28 +00005826 operationCompareStringImplLessEq,
5827 operationCompareStringLessEq,
fpizlo@apple.com12a3fbd2015-11-19 22:18:15 +00005828 operationCompareLessEq);
oliver@apple.com1f9b9b72013-07-25 03:59:52 +00005829 }
5830
5831 void compileCompareGreater()
5832 {
fpizlo@apple.com12a3fbd2015-11-19 22:18:15 +00005833 compare(
5834 [&] (LValue left, LValue right) {
5835 return m_out.greaterThan(left, right);
5836 },
5837 [&] (LValue left, LValue right) {
5838 return m_out.doubleGreaterThan(left, right);
5839 },
commit-queue@webkit.org36c52882016-04-22 05:08:28 +00005840 operationCompareStringImplGreater,
5841 operationCompareStringGreater,
fpizlo@apple.com12a3fbd2015-11-19 22:18:15 +00005842 operationCompareGreater);
oliver@apple.com1f9b9b72013-07-25 03:59:52 +00005843 }
5844
5845 void compileCompareGreaterEq()
5846 {
fpizlo@apple.com12a3fbd2015-11-19 22:18:15 +00005847 compare(
5848 [&] (LValue left, LValue right) {
5849 return m_out.greaterThanOrEqual(left, right);
5850 },
5851 [&] (LValue left, LValue right) {
5852 return m_out.doubleGreaterThanOrEqual(left, right);
5853 },
commit-queue@webkit.org36c52882016-04-22 05:08:28 +00005854 operationCompareStringImplGreaterEq,
5855 operationCompareStringGreaterEq,
fpizlo@apple.com12a3fbd2015-11-19 22:18:15 +00005856 operationCompareGreaterEq);
oliver@apple.comea771492013-07-25 03:58:38 +00005857 }
5858
oliver@apple.com4965ebc2013-07-25 03:59:53 +00005859 void compileLogicalNot()
5860 {
fpizlo@apple.com959a2c42015-12-22 21:59:59 +00005861 setBoolean(m_out.logicalNot(boolify(m_node->child1())));
oliver@apple.com4965ebc2013-07-25 03:59:53 +00005862 }
fpizlo@apple.comb41e6822014-07-25 20:55:17 +00005863
fpizlo@apple.comfa258dc2013-09-07 05:47:57 +00005864 void compileCallOrConstruct()
5865 {
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +00005866 Node* node = m_node;
5867 unsigned numArgs = node->numChildren() - 1;
5868
5869 LValue jsCallee = lowJSValue(m_graph.varArgChild(node, 0));
5870
msaboff@apple.com87644422016-09-21 16:26:13 +00005871 unsigned frameSize = (CallFrame::headerSizeInRegisters + numArgs) * sizeof(EncodedJSValue);
5872 unsigned alignedFrameSize = WTF::roundUpToMultipleOf(stackAlignmentBytes(), frameSize);
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +00005873
5874 // JS->JS calling convention requires that the caller allows this much space on top of stack to
5875 // get trashed by the callee, even if not all of that space is used to pass arguments. We tell
5876 // B3 this explicitly for two reasons:
5877 //
5878 // - We will only pass frameSize worth of stuff.
5879 // - The trashed stack guarantee is logically separate from the act of passing arguments, so we
5880 // shouldn't rely on Air to infer the trashed stack property based on the arguments it ends
5881 // up seeing.
msaboff@apple.com87644422016-09-21 16:26:13 +00005882 m_proc.requestCallArgAreaSizeInBytes(alignedFrameSize);
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +00005883
5884 // Collect the arguments, since this can generate code and we want to generate it before we emit
5885 // the call.
5886 Vector<ConstrainedValue> arguments;
5887
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00005888 // Make sure that the callee goes into GPR0 because that's where the slow path thunks expect the
5889 // callee to be.
5890 arguments.append(ConstrainedValue(jsCallee, ValueRep::reg(GPRInfo::regT0)));
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +00005891
5892 auto addArgument = [&] (LValue value, VirtualRegister reg, int offset) {
5893 intptr_t offsetFromSP =
mark.lam@apple.com2bd89342016-07-08 22:58:15 +00005894 (reg.offset() - CallerFrameAndPC::sizeInRegisters) * sizeof(EncodedJSValue) + offset;
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +00005895 arguments.append(ConstrainedValue(value, ValueRep::stackArgument(offsetFromSP)));
5896 };
5897
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00005898 addArgument(jsCallee, VirtualRegister(CallFrameSlot::callee), 0);
5899 addArgument(m_out.constInt32(numArgs), VirtualRegister(CallFrameSlot::argumentCount), PayloadOffset);
5900 for (unsigned i = 0; i < numArgs; ++i)
5901 addArgument(lowJSValue(m_graph.varArgChild(node, 1 + i)), virtualRegisterForArgument(i), 0);
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +00005902
5903 PatchpointValue* patchpoint = m_out.patchpoint(Int64);
5904 patchpoint->appendVector(arguments);
fpizlo@apple.com090b4dc2016-01-07 23:47:16 +00005905
5906 RefPtr<PatchpointExceptionHandle> exceptionHandle =
5907 preparePatchpointForExceptions(patchpoint);
5908
fpizlo@apple.com4d03e0e2016-04-18 17:13:33 +00005909 patchpoint->append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister));
5910 patchpoint->append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister));
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +00005911 patchpoint->clobber(RegisterSet::macroScratchRegisters());
5912 patchpoint->clobberLate(RegisterSet::volatileRegistersForJSCall());
5913 patchpoint->resultConstraint = ValueRep::reg(GPRInfo::returnValueGPR);
5914
5915 CodeOrigin codeOrigin = codeOriginDescriptionOfCallSite();
5916 State* state = &m_ftlState;
5917 patchpoint->setGenerator(
5918 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
5919 AllowMacroScratchRegisterUsage allowScratch(jit);
5920 CallSiteIndex callSiteIndex = state->jitCode->common.addUniqueCallSiteIndex(codeOrigin);
5921
fpizlo@apple.com090b4dc2016-01-07 23:47:16 +00005922 exceptionHandle->scheduleExitCreationForUnwind(params, callSiteIndex);
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +00005923
5924 jit.store32(
5925 CCallHelpers::TrustedImm32(callSiteIndex.bits()),
mark.lam@apple.com2bd89342016-07-08 22:58:15 +00005926 CCallHelpers::tagFor(VirtualRegister(CallFrameSlot::argumentCount)));
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +00005927
5928 CallLinkInfo* callLinkInfo = jit.codeBlock()->addCallLinkInfo();
5929
5930 CCallHelpers::DataLabelPtr targetToCheck;
5931 CCallHelpers::Jump slowPath = jit.branchPtrWithPatch(
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00005932 CCallHelpers::NotEqual, GPRInfo::regT0, targetToCheck,
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +00005933 CCallHelpers::TrustedImmPtr(0));
5934
5935 CCallHelpers::Call fastCall = jit.nearCall();
5936 CCallHelpers::Jump done = jit.jump();
5937
5938 slowPath.link(&jit);
5939
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00005940 jit.move(CCallHelpers::TrustedImmPtr(callLinkInfo), GPRInfo::regT2);
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +00005941 CCallHelpers::Call slowCall = jit.nearCall();
5942 done.link(&jit);
5943
5944 callLinkInfo->setUpCall(
5945 node->op() == Construct ? CallLinkInfo::Construct : CallLinkInfo::Call,
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00005946 node->origin.semantic, GPRInfo::regT0);
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +00005947
5948 jit.addPtr(
5949 CCallHelpers::TrustedImm32(-params.proc().frameSize()),
5950 GPRInfo::callFrameRegister, CCallHelpers::stackPointerRegister);
5951
5952 jit.addLinkTask(
5953 [=] (LinkBuffer& linkBuffer) {
5954 MacroAssemblerCodePtr linkCall =
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00005955 linkBuffer.vm().getCTIStub(linkCallThunkGenerator).code();
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +00005956 linkBuffer.link(slowCall, FunctionPtr(linkCall.executableAddress()));
5957
5958 callLinkInfo->setCallLocations(
fpizlo@apple.comf0b30cb2016-10-18 18:30:05 +00005959 CodeLocationLabel(linkBuffer.locationOfNearCall(slowCall)),
5960 CodeLocationLabel(linkBuffer.locationOf(targetToCheck)),
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +00005961 linkBuffer.locationOfNearCall(fastCall));
5962 });
5963 });
5964
5965 setJSValue(patchpoint);
fpizlo@apple.comfa258dc2013-09-07 05:47:57 +00005966 }
fpizlo@apple.comf0b30cb2016-10-18 18:30:05 +00005967
5968 void compileDirectCallOrConstruct()
5969 {
5970 Node* node = m_node;
5971 bool isTail = node->op() == DirectTailCall;
5972 bool isConstruct = node->op() == DirectConstruct;
5973
5974 ExecutableBase* executable = node->castOperand<ExecutableBase*>();
5975 FunctionExecutable* functionExecutable = jsDynamicCast<FunctionExecutable*>(executable);
5976
5977 unsigned numPassedArgs = node->numChildren() - 1;
5978 unsigned numAllocatedArgs = numPassedArgs;
5979
5980 if (functionExecutable) {
5981 numAllocatedArgs = std::max(
5982 numAllocatedArgs,
5983 std::min(
5984 static_cast<unsigned>(functionExecutable->parameterCount()) + 1,
5985 Options::maximumDirectCallStackSize()));
5986 }
5987
5988 LValue jsCallee = lowJSValue(m_graph.varArgChild(node, 0));
5989
5990 if (!isTail) {
5991 unsigned frameSize = (CallFrame::headerSizeInRegisters + numAllocatedArgs) * sizeof(EncodedJSValue);
5992 unsigned alignedFrameSize = WTF::roundUpToMultipleOf(stackAlignmentBytes(), frameSize);
5993
5994 m_proc.requestCallArgAreaSizeInBytes(alignedFrameSize);
5995 }
5996
5997 Vector<ConstrainedValue> arguments;
5998
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00005999 arguments.append(ConstrainedValue(jsCallee, ValueRep::SomeRegister));
fpizlo@apple.comf0b30cb2016-10-18 18:30:05 +00006000 if (!isTail) {
6001 auto addArgument = [&] (LValue value, VirtualRegister reg, int offset) {
6002 intptr_t offsetFromSP =
6003 (reg.offset() - CallerFrameAndPC::sizeInRegisters) * sizeof(EncodedJSValue) + offset;
6004 arguments.append(ConstrainedValue(value, ValueRep::stackArgument(offsetFromSP)));
6005 };
msaboff@apple.com26000632016-12-12 21:46:45 +00006006
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00006007 addArgument(jsCallee, VirtualRegister(CallFrameSlot::callee), 0);
6008 addArgument(m_out.constInt32(numPassedArgs), VirtualRegister(CallFrameSlot::argumentCount), PayloadOffset);
6009 for (unsigned i = 0; i < numPassedArgs; ++i)
6010 addArgument(lowJSValue(m_graph.varArgChild(node, 1 + i)), virtualRegisterForArgument(i), 0);
6011 for (unsigned i = numPassedArgs; i < numAllocatedArgs; ++i)
6012 addArgument(m_out.constInt64(JSValue::encode(jsUndefined())), virtualRegisterForArgument(i), 0);
fpizlo@apple.comf0b30cb2016-10-18 18:30:05 +00006013 } else {
6014 for (unsigned i = 0; i < numPassedArgs; ++i)
6015 arguments.append(ConstrainedValue(lowJSValue(m_graph.varArgChild(node, 1 + i)), ValueRep::WarmAny));
6016 }
6017
6018 PatchpointValue* patchpoint = m_out.patchpoint(isTail ? Void : Int64);
6019 patchpoint->appendVector(arguments);
6020
6021 RefPtr<PatchpointExceptionHandle> exceptionHandle = preparePatchpointForExceptions(patchpoint);
6022
6023 if (isTail) {
6024 // The shuffler needs tags.
6025 patchpoint->append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister));
6026 patchpoint->append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister));
6027 }
6028
6029 patchpoint->clobber(RegisterSet::macroScratchRegisters());
6030 if (!isTail) {
6031 patchpoint->clobberLate(RegisterSet::volatileRegistersForJSCall());
6032 patchpoint->resultConstraint = ValueRep::reg(GPRInfo::returnValueGPR);
6033 }
6034
6035 CodeOrigin codeOrigin = codeOriginDescriptionOfCallSite();
6036 State* state = &m_ftlState;
6037 patchpoint->setGenerator(
6038 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
6039 AllowMacroScratchRegisterUsage allowScratch(jit);
6040 CallSiteIndex callSiteIndex = state->jitCode->common.addUniqueCallSiteIndex(codeOrigin);
6041
6042 GPRReg calleeGPR = params[!isTail].gpr();
6043
6044 exceptionHandle->scheduleExitCreationForUnwind(params, callSiteIndex);
6045
6046 Box<CCallHelpers::JumpList> exceptions =
6047 exceptionHandle->scheduleExitCreation(params)->jumps(jit);
6048
6049 if (isTail) {
6050 CallFrameShuffleData shuffleData;
6051 shuffleData.numLocals = state->jitCode->common.frameRegisterCount;
6052
6053 RegisterSet toSave = params.unavailableRegisters();
6054 shuffleData.callee = ValueRecovery::inGPR(calleeGPR, DataFormatCell);
6055 toSave.set(calleeGPR);
6056 for (unsigned i = 0; i < numPassedArgs; ++i) {
6057 ValueRecovery recovery = params[1 + i].recoveryForJSValue();
6058 shuffleData.args.append(recovery);
6059 recovery.forEachReg(
6060 [&] (Reg reg) {
6061 toSave.set(reg);
6062 });
6063 }
6064 for (unsigned i = numPassedArgs; i < numAllocatedArgs; ++i)
6065 shuffleData.args.append(ValueRecovery::constant(jsUndefined()));
fpizlo@apple.com5001f5f2016-12-15 01:25:16 +00006066 shuffleData.numPassedArgs = numPassedArgs;
fpizlo@apple.comf0b30cb2016-10-18 18:30:05 +00006067 shuffleData.setupCalleeSaveRegisters(jit.codeBlock());
6068
6069 CallLinkInfo* callLinkInfo = jit.codeBlock()->addCallLinkInfo();
6070
6071 CCallHelpers::PatchableJump patchableJump = jit.patchableJump();
6072 CCallHelpers::Label mainPath = jit.label();
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00006073
fpizlo@apple.comf0b30cb2016-10-18 18:30:05 +00006074 jit.store32(
6075 CCallHelpers::TrustedImm32(callSiteIndex.bits()),
6076 CCallHelpers::tagFor(VirtualRegister(CallFrameSlot::argumentCount)));
6077
6078 callLinkInfo->setFrameShuffleData(shuffleData);
6079 CallFrameShuffler(jit, shuffleData).prepareForTailCall();
6080
6081 CCallHelpers::Call call = jit.nearTailCall();
6082
6083 jit.abortWithReason(JITDidReturnFromTailCall);
6084
6085 CCallHelpers::Label slowPath = jit.label();
6086 patchableJump.m_jump.linkTo(slowPath, &jit);
6087 callOperation(
6088 *state, toSave, jit,
6089 node->origin.semantic, exceptions.get(), operationLinkDirectCall,
6090 InvalidGPRReg, CCallHelpers::TrustedImmPtr(callLinkInfo), calleeGPR).call();
6091 jit.jump().linkTo(mainPath, &jit);
6092
6093 callLinkInfo->setUpCall(
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00006094 CallLinkInfo::DirectTailCall, node->origin.semantic, InvalidGPRReg);
fpizlo@apple.comf0b30cb2016-10-18 18:30:05 +00006095 callLinkInfo->setExecutableDuringCompilation(executable);
6096 if (numAllocatedArgs > numPassedArgs)
6097 callLinkInfo->setMaxNumArguments(numAllocatedArgs);
6098
6099 jit.addLinkTask(
6100 [=] (LinkBuffer& linkBuffer) {
6101 CodeLocationLabel patchableJumpLocation = linkBuffer.locationOf(patchableJump);
6102 CodeLocationNearCall callLocation = linkBuffer.locationOfNearCall(call);
6103 CodeLocationLabel slowPathLocation = linkBuffer.locationOf(slowPath);
6104
6105 callLinkInfo->setCallLocations(
6106 patchableJumpLocation,
6107 slowPathLocation,
6108 callLocation);
6109 });
6110 return;
6111 }
6112
6113 CallLinkInfo* callLinkInfo = jit.codeBlock()->addCallLinkInfo();
6114
6115 CCallHelpers::Label mainPath = jit.label();
6116
6117 jit.store32(
6118 CCallHelpers::TrustedImm32(callSiteIndex.bits()),
6119 CCallHelpers::tagFor(VirtualRegister(CallFrameSlot::argumentCount)));
6120
6121 CCallHelpers::Call call = jit.nearCall();
6122 jit.addPtr(
6123 CCallHelpers::TrustedImm32(-params.proc().frameSize()),
6124 GPRInfo::callFrameRegister, CCallHelpers::stackPointerRegister);
6125
6126 callLinkInfo->setUpCall(
6127 isConstruct ? CallLinkInfo::DirectConstruct : CallLinkInfo::DirectCall,
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00006128 node->origin.semantic, InvalidGPRReg);
fpizlo@apple.comf0b30cb2016-10-18 18:30:05 +00006129 callLinkInfo->setExecutableDuringCompilation(executable);
6130 if (numAllocatedArgs > numPassedArgs)
6131 callLinkInfo->setMaxNumArguments(numAllocatedArgs);
6132
6133 params.addLatePath(
6134 [=] (CCallHelpers& jit) {
6135 AllowMacroScratchRegisterUsage allowScratch(jit);
6136
6137 CCallHelpers::Label slowPath = jit.label();
6138 if (isX86())
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00006139 jit.pop(CCallHelpers::selectScratchGPR(calleeGPR));
6140
6141 callOperation(
6142 *state, params.unavailableRegisters(), jit,
6143 node->origin.semantic, exceptions.get(), operationLinkDirectCall,
6144 InvalidGPRReg, CCallHelpers::TrustedImmPtr(callLinkInfo),
6145 calleeGPR).call();
fpizlo@apple.comf0b30cb2016-10-18 18:30:05 +00006146 jit.jump().linkTo(mainPath, &jit);
6147
6148 jit.addLinkTask(
6149 [=] (LinkBuffer& linkBuffer) {
6150 CodeLocationNearCall callLocation = linkBuffer.locationOfNearCall(call);
6151 CodeLocationLabel slowPathLocation = linkBuffer.locationOf(slowPath);
6152
6153 linkBuffer.link(call, slowPathLocation);
6154
6155 callLinkInfo->setCallLocations(
6156 CodeLocationLabel(),
6157 slowPathLocation,
6158 callLocation);
6159 });
6160 });
6161 });
6162
6163 if (isTail)
6164 patchpoint->effects.terminal = true;
6165 else
6166 setJSValue(patchpoint);
6167 }
msaboff@apple.comcdd479b2015-09-30 22:28:08 +00006168
6169 void compileTailCall()
6170 {
fpizlo@apple.coma42de462015-12-22 20:03:13 +00006171 Node* node = m_node;
6172 unsigned numArgs = node->numChildren() - 1;
6173
6174 LValue jsCallee = lowJSValue(m_graph.varArgChild(node, 0));
6175
fpizlo@apple.coma42de462015-12-22 20:03:13 +00006176 // We want B3 to give us all of the arguments using whatever mechanism it thinks is
6177 // convenient. The generator then shuffles those arguments into our own call frame,
6178 // destroying our frame in the process.
6179
fpizlo@apple.com090b4dc2016-01-07 23:47:16 +00006180 // Note that we don't have to do anything special for exceptions. A tail call is only a
6181 // tail call if it is not inside a try block.
6182
fpizlo@apple.coma42de462015-12-22 20:03:13 +00006183 Vector<ConstrainedValue> arguments;
6184
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00006185 arguments.append(ConstrainedValue(jsCallee, ValueRep::reg(GPRInfo::regT0)));
fpizlo@apple.coma42de462015-12-22 20:03:13 +00006186
6187 for (unsigned i = 0; i < numArgs; ++i) {
6188 // Note: we could let the shuffler do boxing for us, but it's not super clear that this
6189 // would be better. Also, if we wanted to do that, then we'd have to teach the shuffler
6190 // that 32-bit values could land at 4-byte alignment but not 8-byte alignment.
6191
6192 ConstrainedValue constrainedValue(
6193 lowJSValue(m_graph.varArgChild(node, 1 + i)),
6194 ValueRep::WarmAny);
6195 arguments.append(constrainedValue);
6196 }
6197
6198 PatchpointValue* patchpoint = m_out.patchpoint(Void);
6199 patchpoint->appendVector(arguments);
6200
fpizlo@apple.com4d03e0e2016-04-18 17:13:33 +00006201 patchpoint->append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister));
6202 patchpoint->append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister));
6203
fpizlo@apple.coma42de462015-12-22 20:03:13 +00006204 // Prevent any of the arguments from using the scratch register.
6205 patchpoint->clobberEarly(RegisterSet::macroScratchRegisters());
fpizlo@apple.comf0b30cb2016-10-18 18:30:05 +00006206
6207 patchpoint->effects.terminal = true;
fpizlo@apple.coma42de462015-12-22 20:03:13 +00006208
6209 // We don't have to tell the patchpoint that we will clobber registers, since we won't return
6210 // anyway.
6211
6212 CodeOrigin codeOrigin = codeOriginDescriptionOfCallSite();
fpizlo@apple.comf62d8872016-01-05 23:36:18 +00006213 State* state = &m_ftlState;
fpizlo@apple.coma42de462015-12-22 20:03:13 +00006214 patchpoint->setGenerator(
6215 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
6216 AllowMacroScratchRegisterUsage allowScratch(jit);
fpizlo@apple.coma3c2d402016-02-07 01:51:00 +00006217 CallSiteIndex callSiteIndex = state->jitCode->common.addUniqueCallSiteIndex(codeOrigin);
fpizlo@apple.coma42de462015-12-22 20:03:13 +00006218
msaboff@apple.com9ad52802016-12-12 17:10:30 +00006219 // Yes, this is really necessary. You could throw an exception in a host call on the
6220 // slow path. That'll route us to lookupExceptionHandler(), which unwinds starting
6221 // with the call site index of our frame. Bad things happen if it's not set.
6222 jit.store32(
6223 CCallHelpers::TrustedImm32(callSiteIndex.bits()),
6224 CCallHelpers::tagFor(VirtualRegister(CallFrameSlot::argumentCount)));
6225
fpizlo@apple.coma42de462015-12-22 20:03:13 +00006226 CallFrameShuffleData shuffleData;
fpizlo@apple.comf62d8872016-01-05 23:36:18 +00006227 shuffleData.numLocals = state->jitCode->common.frameRegisterCount;
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00006228 shuffleData.callee = ValueRecovery::inGPR(GPRInfo::regT0, DataFormatJS);
fpizlo@apple.coma42de462015-12-22 20:03:13 +00006229
6230 for (unsigned i = 0; i < numArgs; ++i)
6231 shuffleData.args.append(params[1 + i].recoveryForJSValue());
6232
fpizlo@apple.com5001f5f2016-12-15 01:25:16 +00006233 shuffleData.numPassedArgs = numArgs;
6234
fpizlo@apple.coma42de462015-12-22 20:03:13 +00006235 shuffleData.setupCalleeSaveRegisters(jit.codeBlock());
6236
6237 CallLinkInfo* callLinkInfo = jit.codeBlock()->addCallLinkInfo();
6238
6239 CCallHelpers::DataLabelPtr targetToCheck;
6240 CCallHelpers::Jump slowPath = jit.branchPtrWithPatch(
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00006241 CCallHelpers::NotEqual, GPRInfo::regT0, targetToCheck,
fpizlo@apple.coma42de462015-12-22 20:03:13 +00006242 CCallHelpers::TrustedImmPtr(0));
6243
6244 callLinkInfo->setFrameShuffleData(shuffleData);
6245 CallFrameShuffler(jit, shuffleData).prepareForTailCall();
6246
6247 CCallHelpers::Call fastCall = jit.nearTailCall();
6248
6249 slowPath.link(&jit);
6250
fpizlo@apple.coma42de462015-12-22 20:03:13 +00006251 CallFrameShuffler slowPathShuffler(jit, shuffleData);
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00006252 slowPathShuffler.setCalleeJSValueRegs(JSValueRegs(GPRInfo::regT0));
fpizlo@apple.coma42de462015-12-22 20:03:13 +00006253 slowPathShuffler.prepareForSlowPath();
6254
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00006255 jit.move(CCallHelpers::TrustedImmPtr(callLinkInfo), GPRInfo::regT2);
fpizlo@apple.coma42de462015-12-22 20:03:13 +00006256 CCallHelpers::Call slowCall = jit.nearCall();
6257
6258 jit.abortWithReason(JITDidReturnFromTailCall);
6259
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00006260 callLinkInfo->setUpCall(CallLinkInfo::TailCall, codeOrigin, GPRInfo::regT0);
fpizlo@apple.coma42de462015-12-22 20:03:13 +00006261
6262 jit.addLinkTask(
6263 [=] (LinkBuffer& linkBuffer) {
6264 MacroAssemblerCodePtr linkCall =
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00006265 linkBuffer.vm().getCTIStub(linkCallThunkGenerator).code();
fpizlo@apple.coma42de462015-12-22 20:03:13 +00006266 linkBuffer.link(slowCall, FunctionPtr(linkCall.executableAddress()));
6267
6268 callLinkInfo->setCallLocations(
fpizlo@apple.comf0b30cb2016-10-18 18:30:05 +00006269 CodeLocationLabel(linkBuffer.locationOfNearCall(slowCall)),
6270 CodeLocationLabel(linkBuffer.locationOf(targetToCheck)),
fpizlo@apple.coma42de462015-12-22 20:03:13 +00006271 linkBuffer.locationOfNearCall(fastCall));
6272 });
6273 });
msaboff@apple.comcdd479b2015-09-30 22:28:08 +00006274 }
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +00006275
sbarati@apple.come20444a2016-11-30 06:24:44 +00006276 void compileCallOrConstructVarargsSpread()
6277 {
6278 Node* node = m_node;
6279 LValue jsCallee = lowJSValue(m_node->child1());
6280 LValue thisArg = lowJSValue(m_node->child2());
6281
6282 RELEASE_ASSERT(node->child3()->op() == PhantomNewArrayWithSpread);
6283 Node* arrayWithSpread = node->child3().node();
6284 BitVector* bitVector = arrayWithSpread->bitVector();
6285 unsigned numNonSpreadParameters = 0;
6286 Vector<LValue, 2> spreadLengths;
6287 Vector<LValue, 8> patchpointArguments;
6288 HashMap<InlineCallFrame*, LValue, WTF::DefaultHash<InlineCallFrame*>::Hash, WTF::NullableHashTraits<InlineCallFrame*>> cachedSpreadLengths;
6289
6290 for (unsigned i = 0; i < arrayWithSpread->numChildren(); i++) {
6291 if (bitVector->get(i)) {
6292 Node* spread = m_graph.varArgChild(arrayWithSpread, i).node();
6293 RELEASE_ASSERT(spread->op() == PhantomSpread);
6294 RELEASE_ASSERT(spread->child1()->op() == PhantomCreateRest);
6295 InlineCallFrame* inlineCallFrame = spread->child1()->origin.semantic.inlineCallFrame;
6296 unsigned numberOfArgumentsToSkip = spread->child1()->numberOfArgumentsToSkip();
6297 LValue length = cachedSpreadLengths.ensure(inlineCallFrame, [&] () {
6298 return m_out.zeroExtPtr(getSpreadLengthFromInlineCallFrame(inlineCallFrame, numberOfArgumentsToSkip));
6299 }).iterator->value;
6300 patchpointArguments.append(length);
6301 spreadLengths.append(length);
6302 } else {
6303 ++numNonSpreadParameters;
6304 LValue argument = lowJSValue(m_graph.varArgChild(arrayWithSpread, i));
6305 patchpointArguments.append(argument);
6306 }
6307 }
6308
6309 LValue argumentCountIncludingThis = m_out.constIntPtr(numNonSpreadParameters + 1);
6310 for (LValue length : spreadLengths)
6311 argumentCountIncludingThis = m_out.add(length, argumentCountIncludingThis);
6312
6313 PatchpointValue* patchpoint = m_out.patchpoint(Int64);
6314
6315 patchpoint->append(jsCallee, ValueRep::reg(GPRInfo::regT0));
6316 patchpoint->append(thisArg, ValueRep::WarmAny);
6317 patchpoint->append(argumentCountIncludingThis, ValueRep::WarmAny);
6318 patchpoint->appendVectorWithRep(patchpointArguments, ValueRep::WarmAny);
6319 patchpoint->append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister));
6320 patchpoint->append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister));
6321
6322 RefPtr<PatchpointExceptionHandle> exceptionHandle = preparePatchpointForExceptions(patchpoint);
6323
6324 patchpoint->clobber(RegisterSet::macroScratchRegisters());
6325 patchpoint->clobber(RegisterSet::volatileRegistersForJSCall()); // No inputs will be in a volatile register.
6326 patchpoint->resultConstraint = ValueRep::reg(GPRInfo::returnValueGPR);
6327
6328 patchpoint->numGPScratchRegisters = 0;
6329
6330 // This is the minimum amount of call arg area stack space that all JS->JS calls always have.
6331 unsigned minimumJSCallAreaSize =
6332 sizeof(CallerFrameAndPC) +
6333 WTF::roundUpToMultipleOf(stackAlignmentBytes(), 5 * sizeof(EncodedJSValue));
6334
6335 m_proc.requestCallArgAreaSizeInBytes(minimumJSCallAreaSize);
6336
6337 CodeOrigin codeOrigin = codeOriginDescriptionOfCallSite();
6338 State* state = &m_ftlState;
6339 patchpoint->setGenerator(
6340 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
6341 AllowMacroScratchRegisterUsage allowScratch(jit);
6342 CallSiteIndex callSiteIndex =
6343 state->jitCode->common.addUniqueCallSiteIndex(codeOrigin);
6344
6345 Box<CCallHelpers::JumpList> exceptions =
6346 exceptionHandle->scheduleExitCreation(params)->jumps(jit);
6347
6348 exceptionHandle->scheduleExitCreationForUnwind(params, callSiteIndex);
6349
6350 jit.store32(
6351 CCallHelpers::TrustedImm32(callSiteIndex.bits()),
6352 CCallHelpers::tagFor(VirtualRegister(CallFrameSlot::argumentCount)));
6353
6354 CallLinkInfo* callLinkInfo = jit.codeBlock()->addCallLinkInfo();
6355
6356 RegisterSet usedRegisters = RegisterSet::allRegisters();
6357 usedRegisters.exclude(RegisterSet::volatileRegistersForJSCall());
6358 GPRReg calleeGPR = params[1].gpr();
6359 usedRegisters.set(calleeGPR);
6360
6361 ScratchRegisterAllocator allocator(usedRegisters);
6362 GPRReg scratchGPR1 = allocator.allocateScratchGPR();
6363 GPRReg scratchGPR2 = allocator.allocateScratchGPR();
6364 GPRReg scratchGPR3 = allocator.allocateScratchGPR();
6365 GPRReg scratchGPR4 = allocator.allocateScratchGPR();
6366 RELEASE_ASSERT(!allocator.numberOfReusedRegisters());
6367
6368 auto getValueFromRep = [&] (B3::ValueRep rep, GPRReg result) {
6369 ASSERT(!usedRegisters.get(result));
6370
6371 if (rep.isConstant()) {
6372 jit.move(CCallHelpers::Imm64(rep.value()), result);
6373 return;
6374 }
6375
6376 // Note: in this function, we only request 64 bit values.
6377 if (rep.isStack()) {
6378 jit.load64(
6379 CCallHelpers::Address(GPRInfo::callFrameRegister, rep.offsetFromFP()),
6380 result);
6381 return;
6382 }
6383
6384 RELEASE_ASSERT(rep.isGPR());
6385 ASSERT(usedRegisters.get(rep.gpr()));
6386 jit.move(rep.gpr(), result);
6387 };
6388
6389 auto callWithExceptionCheck = [&] (void* callee) {
6390 jit.move(CCallHelpers::TrustedImmPtr(callee), GPRInfo::nonPreservedNonArgumentGPR);
6391 jit.call(GPRInfo::nonPreservedNonArgumentGPR);
6392 exceptions->append(jit.emitExceptionCheck(AssemblyHelpers::NormalExceptionCheck, AssemblyHelpers::FarJumpWidth));
6393 };
6394
6395 auto adjustStack = [&] (GPRReg amount) {
6396 jit.addPtr(CCallHelpers::TrustedImm32(sizeof(CallerFrameAndPC)), amount, CCallHelpers::stackPointerRegister);
6397 };
6398
6399 CCallHelpers::JumpList slowCase;
6400 unsigned originalStackHeight = params.proc().frameSize();
6401
6402 {
6403 unsigned numUsedSlots = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), originalStackHeight / sizeof(EncodedJSValue));
6404 B3::ValueRep argumentCountIncludingThisRep = params[3];
6405 getValueFromRep(argumentCountIncludingThisRep, scratchGPR2);
6406 slowCase.append(jit.branch32(CCallHelpers::Above, scratchGPR2, CCallHelpers::TrustedImm32(JSC::maxArguments + 1)));
6407
6408 jit.move(scratchGPR2, scratchGPR1);
6409 jit.addPtr(CCallHelpers::TrustedImmPtr(static_cast<size_t>(numUsedSlots + CallFrame::headerSizeInRegisters)), scratchGPR1);
6410 // scratchGPR1 now has the required frame size in Register units
6411 // Round scratchGPR1 to next multiple of stackAlignmentRegisters()
6412 jit.addPtr(CCallHelpers::TrustedImm32(stackAlignmentRegisters() - 1), scratchGPR1);
6413 jit.andPtr(CCallHelpers::TrustedImm32(~(stackAlignmentRegisters() - 1)), scratchGPR1);
6414 jit.negPtr(scratchGPR1);
6415 jit.lshiftPtr(CCallHelpers::Imm32(3), scratchGPR1);
6416 jit.addPtr(GPRInfo::callFrameRegister, scratchGPR1);
6417
6418 jit.store32(scratchGPR2, CCallHelpers::Address(scratchGPR1, CallFrameSlot::argumentCount * static_cast<int>(sizeof(Register)) + PayloadOffset));
6419
6420 int storeOffset = CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register));
6421
6422 for (unsigned i = arrayWithSpread->numChildren(); i--; ) {
6423 unsigned paramsOffset = 4;
6424
6425 if (bitVector->get(i)) {
6426 Node* spread = state->graph.varArgChild(arrayWithSpread, i).node();
6427 RELEASE_ASSERT(spread->op() == PhantomSpread);
6428 RELEASE_ASSERT(spread->child1()->op() == PhantomCreateRest);
6429 InlineCallFrame* inlineCallFrame = spread->child1()->origin.semantic.inlineCallFrame;
6430
6431 unsigned numberOfArgumentsToSkip = spread->child1()->numberOfArgumentsToSkip();
6432
6433 B3::ValueRep numArgumentsToCopy = params[paramsOffset + i];
6434 getValueFromRep(numArgumentsToCopy, scratchGPR3);
6435 int loadOffset = (AssemblyHelpers::argumentsStart(inlineCallFrame).offset() + numberOfArgumentsToSkip) * static_cast<int>(sizeof(Register));
6436
6437 auto done = jit.branchTestPtr(MacroAssembler::Zero, scratchGPR3);
6438 auto loopStart = jit.label();
6439 jit.subPtr(CCallHelpers::TrustedImmPtr(static_cast<size_t>(1)), scratchGPR3);
6440 jit.subPtr(CCallHelpers::TrustedImmPtr(static_cast<size_t>(1)), scratchGPR2);
6441 jit.load64(CCallHelpers::BaseIndex(GPRInfo::callFrameRegister, scratchGPR3, CCallHelpers::TimesEight, loadOffset), scratchGPR4);
6442 jit.store64(scratchGPR4,
6443 CCallHelpers::BaseIndex(scratchGPR1, scratchGPR2, CCallHelpers::TimesEight, storeOffset));
6444 jit.branchTestPtr(CCallHelpers::NonZero, scratchGPR3).linkTo(loopStart, &jit);
6445 done.link(&jit);
6446 } else {
6447 jit.subPtr(CCallHelpers::TrustedImmPtr(static_cast<size_t>(1)), scratchGPR2);
6448 getValueFromRep(params[paramsOffset + i], scratchGPR3);
6449 jit.store64(scratchGPR3,
6450 CCallHelpers::BaseIndex(scratchGPR1, scratchGPR2, CCallHelpers::TimesEight, storeOffset));
6451 }
6452 }
6453 }
6454
6455 {
6456 CCallHelpers::Jump dontThrow = jit.jump();
6457 slowCase.link(&jit);
6458 jit.setupArgumentsExecState();
6459 callWithExceptionCheck(bitwise_cast<void*>(operationThrowStackOverflowForVarargs));
6460 jit.abortWithReason(DFGVarargsThrowingPathDidNotThrow);
6461
6462 dontThrow.link(&jit);
6463 }
6464
6465 adjustStack(scratchGPR1);
6466
6467 ASSERT(calleeGPR == GPRInfo::regT0);
6468 jit.store64(calleeGPR, CCallHelpers::calleeFrameSlot(CallFrameSlot::callee));
6469 getValueFromRep(params[2], scratchGPR3);
6470 jit.store64(scratchGPR3, CCallHelpers::calleeArgumentSlot(0));
6471
6472 CallLinkInfo::CallType callType;
6473 if (node->op() == ConstructVarargs || node->op() == ConstructForwardVarargs)
6474 callType = CallLinkInfo::ConstructVarargs;
6475 else if (node->op() == TailCallVarargs || node->op() == TailCallForwardVarargs)
6476 callType = CallLinkInfo::TailCallVarargs;
6477 else
6478 callType = CallLinkInfo::CallVarargs;
6479
6480 bool isTailCall = CallLinkInfo::callModeFor(callType) == CallMode::Tail;
6481
6482 CCallHelpers::DataLabelPtr targetToCheck;
6483 CCallHelpers::Jump slowPath = jit.branchPtrWithPatch(
6484 CCallHelpers::NotEqual, GPRInfo::regT0, targetToCheck,
6485 CCallHelpers::TrustedImmPtr(nullptr));
6486
6487 CCallHelpers::Call fastCall;
6488 CCallHelpers::Jump done;
6489
6490 if (isTailCall) {
6491 jit.emitRestoreCalleeSaves();
6492 jit.prepareForTailCallSlow();
6493 fastCall = jit.nearTailCall();
6494 } else {
6495 fastCall = jit.nearCall();
6496 done = jit.jump();
6497 }
6498
6499 slowPath.link(&jit);
6500
6501 if (isTailCall)
6502 jit.emitRestoreCalleeSaves();
6503 ASSERT(!usedRegisters.get(GPRInfo::regT2));
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00006504 jit.move(CCallHelpers::TrustedImmPtr(callLinkInfo), GPRInfo::regT2);
sbarati@apple.come20444a2016-11-30 06:24:44 +00006505 CCallHelpers::Call slowCall = jit.nearCall();
6506
6507 if (isTailCall)
6508 jit.abortWithReason(JITDidReturnFromTailCall);
6509 else
6510 done.link(&jit);
6511
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00006512 callLinkInfo->setUpCall(callType, node->origin.semantic, GPRInfo::regT0);
sbarati@apple.come20444a2016-11-30 06:24:44 +00006513
6514 jit.addPtr(
6515 CCallHelpers::TrustedImm32(-originalStackHeight),
6516 GPRInfo::callFrameRegister, CCallHelpers::stackPointerRegister);
6517
6518 jit.addLinkTask(
6519 [=] (LinkBuffer& linkBuffer) {
6520 MacroAssemblerCodePtr linkCall =
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00006521 linkBuffer.vm().getCTIStub(linkCallThunkGenerator).code();
sbarati@apple.come20444a2016-11-30 06:24:44 +00006522 linkBuffer.link(slowCall, FunctionPtr(linkCall.executableAddress()));
6523
6524 callLinkInfo->setCallLocations(
6525 CodeLocationLabel(linkBuffer.locationOfNearCall(slowCall)),
6526 CodeLocationLabel(linkBuffer.locationOf(targetToCheck)),
6527 linkBuffer.locationOfNearCall(fastCall));
6528 });
6529 });
6530
6531 switch (node->op()) {
6532 case TailCallForwardVarargs:
6533 m_out.unreachable();
6534 break;
6535
6536 default:
6537 setJSValue(patchpoint);
6538 break;
6539 }
6540 }
6541
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +00006542 void compileCallOrConstructVarargs()
6543 {
fpizlo@apple.com203ebdb2015-12-21 18:56:54 +00006544 Node* node = m_node;
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +00006545 LValue jsCallee = lowJSValue(m_node->child1());
keith_miller@apple.come497e202016-06-13 21:05:36 +00006546 LValue thisArg = lowJSValue(m_node->child2());
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +00006547
6548 LValue jsArguments = nullptr;
fpizlo@apple.com203ebdb2015-12-21 18:56:54 +00006549 bool forwarding = false;
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +00006550
fpizlo@apple.com203ebdb2015-12-21 18:56:54 +00006551 switch (node->op()) {
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +00006552 case CallVarargs:
msaboff@apple.comcdd479b2015-09-30 22:28:08 +00006553 case TailCallVarargs:
6554 case TailCallVarargsInlinedCaller:
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +00006555 case ConstructVarargs:
keith_miller@apple.come497e202016-06-13 21:05:36 +00006556 jsArguments = lowJSValue(node->child3());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00006557 break;
6558 case CallForwardVarargs:
msaboff@apple.comcdd479b2015-09-30 22:28:08 +00006559 case TailCallForwardVarargs:
6560 case TailCallForwardVarargsInlinedCaller:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00006561 case ConstructForwardVarargs:
fpizlo@apple.com203ebdb2015-12-21 18:56:54 +00006562 forwarding = true;
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +00006563 break;
6564 default:
fpizlo@apple.com203ebdb2015-12-21 18:56:54 +00006565 DFG_CRASH(m_graph, node, "bad node type");
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +00006566 break;
6567 }
sbarati@apple.come20444a2016-11-30 06:24:44 +00006568
6569 if (forwarding && m_node->child3() && m_node->child3()->op() == PhantomNewArrayWithSpread) {
6570 compileCallOrConstructVarargsSpread();
6571 return;
6572 }
6573
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +00006574
fpizlo@apple.com203ebdb2015-12-21 18:56:54 +00006575 PatchpointValue* patchpoint = m_out.patchpoint(Int64);
6576
6577 // Append the forms of the arguments that we will use before any clobbering happens.
6578 patchpoint->append(jsCallee, ValueRep::reg(GPRInfo::regT0));
6579 if (jsArguments)
fpizlo@apple.com45e45652016-01-07 21:20:37 +00006580 patchpoint->appendSomeRegister(jsArguments);
6581 patchpoint->appendSomeRegister(thisArg);
fpizlo@apple.com203ebdb2015-12-21 18:56:54 +00006582
6583 if (!forwarding) {
6584 // Now append them again for after clobbering. Note that the compiler may ask us to use a
6585 // different register for the late for the post-clobbering version of the value. This gives
6586 // the compiler a chance to spill these values without having to burn any callee-saves.
6587 patchpoint->append(jsCallee, ValueRep::LateColdAny);
6588 patchpoint->append(jsArguments, ValueRep::LateColdAny);
6589 patchpoint->append(thisArg, ValueRep::LateColdAny);
6590 }
6591
fpizlo@apple.com090b4dc2016-01-07 23:47:16 +00006592 RefPtr<PatchpointExceptionHandle> exceptionHandle =
6593 preparePatchpointForExceptions(patchpoint);
6594
fpizlo@apple.com4d03e0e2016-04-18 17:13:33 +00006595 patchpoint->append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister));
6596 patchpoint->append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister));
6597
fpizlo@apple.com203ebdb2015-12-21 18:56:54 +00006598 patchpoint->clobber(RegisterSet::macroScratchRegisters());
6599 patchpoint->clobberLate(RegisterSet::volatileRegistersForJSCall());
6600 patchpoint->resultConstraint = ValueRep::reg(GPRInfo::returnValueGPR);
6601
6602 // This is the minimum amount of call arg area stack space that all JS->JS calls always have.
6603 unsigned minimumJSCallAreaSize =
6604 sizeof(CallerFrameAndPC) +
6605 WTF::roundUpToMultipleOf(stackAlignmentBytes(), 5 * sizeof(EncodedJSValue));
6606
msaboff@apple.com87644422016-09-21 16:26:13 +00006607 m_proc.requestCallArgAreaSizeInBytes(minimumJSCallAreaSize);
fpizlo@apple.com203ebdb2015-12-21 18:56:54 +00006608
6609 CodeOrigin codeOrigin = codeOriginDescriptionOfCallSite();
6610 State* state = &m_ftlState;
6611 patchpoint->setGenerator(
6612 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
6613 AllowMacroScratchRegisterUsage allowScratch(jit);
6614 CallSiteIndex callSiteIndex =
6615 state->jitCode->common.addUniqueCallSiteIndex(codeOrigin);
6616
fpizlo@apple.com090b4dc2016-01-07 23:47:16 +00006617 Box<CCallHelpers::JumpList> exceptions =
6618 exceptionHandle->scheduleExitCreation(params)->jumps(jit);
6619
6620 exceptionHandle->scheduleExitCreationForUnwind(params, callSiteIndex);
fpizlo@apple.com203ebdb2015-12-21 18:56:54 +00006621
6622 jit.store32(
6623 CCallHelpers::TrustedImm32(callSiteIndex.bits()),
mark.lam@apple.com2bd89342016-07-08 22:58:15 +00006624 CCallHelpers::tagFor(VirtualRegister(CallFrameSlot::argumentCount)));
fpizlo@apple.com203ebdb2015-12-21 18:56:54 +00006625
6626 CallLinkInfo* callLinkInfo = jit.codeBlock()->addCallLinkInfo();
6627 CallVarargsData* data = node->callVarargsData();
6628
6629 unsigned argIndex = 1;
6630 GPRReg calleeGPR = params[argIndex++].gpr();
6631 ASSERT(calleeGPR == GPRInfo::regT0);
6632 GPRReg argumentsGPR = jsArguments ? params[argIndex++].gpr() : InvalidGPRReg;
6633 GPRReg thisGPR = params[argIndex++].gpr();
6634
6635 B3::ValueRep calleeLateRep;
6636 B3::ValueRep argumentsLateRep;
6637 B3::ValueRep thisLateRep;
6638 if (!forwarding) {
6639 // If we're not forwarding then we'll need callee, arguments, and this after we
6640 // have potentially clobbered calleeGPR, argumentsGPR, and thisGPR. Our technique
6641 // for this is to supply all of those operands as late uses in addition to
6642 // specifying them as early uses. It's possible that the late use uses a spill
6643 // while the early use uses a register, and it's possible for the late and early
6644 // uses to use different registers. We do know that the late uses interfere with
6645 // all volatile registers and so won't use those, but the early uses may use
6646 // volatile registers and in the case of calleeGPR, it's pinned to regT0 so it
6647 // definitely will.
6648 //
6649 // Note that we have to be super careful with these. It's possible that these
6650 // use a shuffling of the registers used for calleeGPR, argumentsGPR, and
6651 // thisGPR. If that happens and we do for example:
6652 //
6653 // calleeLateRep.emitRestore(jit, calleeGPR);
6654 // argumentsLateRep.emitRestore(jit, calleeGPR);
6655 //
6656 // Then we might end up with garbage if calleeLateRep.gpr() == argumentsGPR and
6657 // argumentsLateRep.gpr() == calleeGPR.
6658 //
6659 // We do a variety of things to prevent this from happening. For example, we use
6660 // argumentsLateRep before needing the other two and after we've already stopped
6661 // using the *GPRs. Also, we pin calleeGPR to regT0, and rely on the fact that
6662 // the *LateReps cannot use volatile registers (so they cannot be regT0, so
6663 // calleeGPR != argumentsLateRep.gpr() and calleeGPR != thisLateRep.gpr()).
6664 //
6665 // An alternative would have been to just use early uses and early-clobber all
6666 // volatile registers. But that would force callee, arguments, and this into
6667 // callee-save registers even if we have to spill them. We don't want spilling to
6668 // use up three callee-saves.
6669 //
6670 // TL;DR: The way we use LateReps here is dangerous and barely works but achieves
6671 // some desirable performance properties, so don't mistake the cleverness for
6672 // elegance.
6673 calleeLateRep = params[argIndex++];
6674 argumentsLateRep = params[argIndex++];
6675 thisLateRep = params[argIndex++];
6676 }
6677
6678 // Get some scratch registers.
6679 RegisterSet usedRegisters;
6680 usedRegisters.merge(RegisterSet::stackRegisters());
6681 usedRegisters.merge(RegisterSet::reservedHardwareRegisters());
6682 usedRegisters.merge(RegisterSet::calleeSaveRegisters());
6683 usedRegisters.set(calleeGPR);
6684 if (argumentsGPR != InvalidGPRReg)
6685 usedRegisters.set(argumentsGPR);
6686 usedRegisters.set(thisGPR);
6687 if (calleeLateRep.isReg())
6688 usedRegisters.set(calleeLateRep.reg());
6689 if (argumentsLateRep.isReg())
6690 usedRegisters.set(argumentsLateRep.reg());
6691 if (thisLateRep.isReg())
6692 usedRegisters.set(thisLateRep.reg());
6693 ScratchRegisterAllocator allocator(usedRegisters);
6694 GPRReg scratchGPR1 = allocator.allocateScratchGPR();
6695 GPRReg scratchGPR2 = allocator.allocateScratchGPR();
6696 GPRReg scratchGPR3 = forwarding ? allocator.allocateScratchGPR() : InvalidGPRReg;
6697 RELEASE_ASSERT(!allocator.numberOfReusedRegisters());
6698
6699 auto callWithExceptionCheck = [&] (void* callee) {
6700 jit.move(CCallHelpers::TrustedImmPtr(callee), GPRInfo::nonPreservedNonArgumentGPR);
6701 jit.call(GPRInfo::nonPreservedNonArgumentGPR);
fpizlo@apple.com090b4dc2016-01-07 23:47:16 +00006702 exceptions->append(jit.emitExceptionCheck(AssemblyHelpers::NormalExceptionCheck, AssemblyHelpers::FarJumpWidth));
fpizlo@apple.com203ebdb2015-12-21 18:56:54 +00006703 };
6704
6705 auto adjustStack = [&] (GPRReg amount) {
6706 jit.addPtr(CCallHelpers::TrustedImm32(sizeof(CallerFrameAndPC)), amount, CCallHelpers::stackPointerRegister);
6707 };
6708
6709 unsigned originalStackHeight = params.proc().frameSize();
6710
6711 if (forwarding) {
6712 jit.move(CCallHelpers::TrustedImm32(originalStackHeight / sizeof(EncodedJSValue)), scratchGPR2);
6713
6714 CCallHelpers::JumpList slowCase;
keith_miller@apple.come497e202016-06-13 21:05:36 +00006715 InlineCallFrame* inlineCallFrame;
6716 if (node->child3())
6717 inlineCallFrame = node->child3()->origin.semantic.inlineCallFrame;
6718 else
6719 inlineCallFrame = node->origin.semantic.inlineCallFrame;
6720 emitSetupVarargsFrameFastCase(jit, scratchGPR2, scratchGPR1, scratchGPR2, scratchGPR3, inlineCallFrame, data->firstVarArgOffset, slowCase);
fpizlo@apple.com203ebdb2015-12-21 18:56:54 +00006721
6722 CCallHelpers::Jump done = jit.jump();
6723 slowCase.link(&jit);
6724 jit.setupArgumentsExecState();
6725 callWithExceptionCheck(bitwise_cast<void*>(operationThrowStackOverflowForVarargs));
6726 jit.abortWithReason(DFGVarargsThrowingPathDidNotThrow);
6727
6728 done.link(&jit);
6729
6730 adjustStack(scratchGPR2);
6731 } else {
6732 jit.move(CCallHelpers::TrustedImm32(originalStackHeight / sizeof(EncodedJSValue)), scratchGPR1);
6733 jit.setupArgumentsWithExecState(argumentsGPR, scratchGPR1, CCallHelpers::TrustedImm32(data->firstVarArgOffset));
6734 callWithExceptionCheck(bitwise_cast<void*>(operationSizeFrameForVarargs));
6735
6736 jit.move(GPRInfo::returnValueGPR, scratchGPR1);
6737 jit.move(CCallHelpers::TrustedImm32(originalStackHeight / sizeof(EncodedJSValue)), scratchGPR2);
6738 argumentsLateRep.emitRestore(jit, argumentsGPR);
6739 emitSetVarargsFrame(jit, scratchGPR1, false, scratchGPR2, scratchGPR2);
6740 jit.addPtr(CCallHelpers::TrustedImm32(-minimumJSCallAreaSize), scratchGPR2, CCallHelpers::stackPointerRegister);
6741 jit.setupArgumentsWithExecState(scratchGPR2, argumentsGPR, CCallHelpers::TrustedImm32(data->firstVarArgOffset), scratchGPR1);
6742 callWithExceptionCheck(bitwise_cast<void*>(operationSetupVarargsFrame));
6743
6744 adjustStack(GPRInfo::returnValueGPR);
6745
6746 calleeLateRep.emitRestore(jit, GPRInfo::regT0);
6747
6748 // This may not emit code if thisGPR got a callee-save. Also, we're guaranteed
6749 // that thisGPR != GPRInfo::regT0 because regT0 interferes with it.
6750 thisLateRep.emitRestore(jit, thisGPR);
6751 }
6752
mark.lam@apple.com2bd89342016-07-08 22:58:15 +00006753 jit.store64(GPRInfo::regT0, CCallHelpers::calleeFrameSlot(CallFrameSlot::callee));
fpizlo@apple.com203ebdb2015-12-21 18:56:54 +00006754 jit.store64(thisGPR, CCallHelpers::calleeArgumentSlot(0));
6755
6756 CallLinkInfo::CallType callType;
6757 if (node->op() == ConstructVarargs || node->op() == ConstructForwardVarargs)
6758 callType = CallLinkInfo::ConstructVarargs;
6759 else if (node->op() == TailCallVarargs || node->op() == TailCallForwardVarargs)
6760 callType = CallLinkInfo::TailCallVarargs;
6761 else
6762 callType = CallLinkInfo::CallVarargs;
6763
6764 bool isTailCall = CallLinkInfo::callModeFor(callType) == CallMode::Tail;
6765
6766 CCallHelpers::DataLabelPtr targetToCheck;
6767 CCallHelpers::Jump slowPath = jit.branchPtrWithPatch(
6768 CCallHelpers::NotEqual, GPRInfo::regT0, targetToCheck,
6769 CCallHelpers::TrustedImmPtr(0));
6770
6771 CCallHelpers::Call fastCall;
6772 CCallHelpers::Jump done;
6773
6774 if (isTailCall) {
commit-queue@webkit.org5486b852016-01-28 08:52:44 +00006775 jit.emitRestoreCalleeSaves();
fpizlo@apple.com203ebdb2015-12-21 18:56:54 +00006776 jit.prepareForTailCallSlow();
6777 fastCall = jit.nearTailCall();
6778 } else {
6779 fastCall = jit.nearCall();
6780 done = jit.jump();
6781 }
6782
6783 slowPath.link(&jit);
commit-queue@webkit.org5486b852016-01-28 08:52:44 +00006784
6785 if (isTailCall)
6786 jit.emitRestoreCalleeSaves();
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00006787 jit.move(CCallHelpers::TrustedImmPtr(callLinkInfo), GPRInfo::regT2);
fpizlo@apple.com203ebdb2015-12-21 18:56:54 +00006788 CCallHelpers::Call slowCall = jit.nearCall();
6789
6790 if (isTailCall)
6791 jit.abortWithReason(JITDidReturnFromTailCall);
6792 else
6793 done.link(&jit);
6794
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00006795 callLinkInfo->setUpCall(callType, node->origin.semantic, GPRInfo::regT0);
fpizlo@apple.com203ebdb2015-12-21 18:56:54 +00006796
6797 jit.addPtr(
6798 CCallHelpers::TrustedImm32(-originalStackHeight),
6799 GPRInfo::callFrameRegister, CCallHelpers::stackPointerRegister);
6800
6801 jit.addLinkTask(
6802 [=] (LinkBuffer& linkBuffer) {
6803 MacroAssemblerCodePtr linkCall =
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00006804 linkBuffer.vm().getCTIStub(linkCallThunkGenerator).code();
fpizlo@apple.com203ebdb2015-12-21 18:56:54 +00006805 linkBuffer.link(slowCall, FunctionPtr(linkCall.executableAddress()));
6806
6807 callLinkInfo->setCallLocations(
fpizlo@apple.comf0b30cb2016-10-18 18:30:05 +00006808 CodeLocationLabel(linkBuffer.locationOfNearCall(slowCall)),
6809 CodeLocationLabel(linkBuffer.locationOf(targetToCheck)),
fpizlo@apple.com203ebdb2015-12-21 18:56:54 +00006810 linkBuffer.locationOfNearCall(fastCall));
6811 });
6812 });
6813
fpizlo@apple.comdfefc4a2016-01-09 00:37:47 +00006814 switch (node->op()) {
6815 case TailCallVarargs:
6816 case TailCallForwardVarargs:
6817 m_out.unreachable();
6818 break;
6819
6820 default:
6821 setJSValue(patchpoint);
6822 break;
6823 }
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +00006824 }
6825
fpizlo@apple.com48bf58d2016-07-18 19:32:34 +00006826 void compileCallEval()
6827 {
6828 Node* node = m_node;
6829 unsigned numArgs = node->numChildren() - 1;
6830
6831 LValue jsCallee = lowJSValue(m_graph.varArgChild(node, 0));
6832
msaboff@apple.com87644422016-09-21 16:26:13 +00006833 unsigned frameSize = (CallFrame::headerSizeInRegisters + numArgs) * sizeof(EncodedJSValue);
6834 unsigned alignedFrameSize = WTF::roundUpToMultipleOf(stackAlignmentBytes(), frameSize);
fpizlo@apple.com48bf58d2016-07-18 19:32:34 +00006835
msaboff@apple.com87644422016-09-21 16:26:13 +00006836 m_proc.requestCallArgAreaSizeInBytes(alignedFrameSize);
fpizlo@apple.com48bf58d2016-07-18 19:32:34 +00006837
6838 Vector<ConstrainedValue> arguments;
6839 arguments.append(ConstrainedValue(jsCallee, ValueRep::reg(GPRInfo::regT0)));
6840
6841 auto addArgument = [&] (LValue value, VirtualRegister reg, int offset) {
6842 intptr_t offsetFromSP =
6843 (reg.offset() - CallerFrameAndPC::sizeInRegisters) * sizeof(EncodedJSValue) + offset;
6844 arguments.append(ConstrainedValue(value, ValueRep::stackArgument(offsetFromSP)));
6845 };
6846
6847 addArgument(jsCallee, VirtualRegister(CallFrameSlot::callee), 0);
6848 addArgument(m_out.constInt32(numArgs), VirtualRegister(CallFrameSlot::argumentCount), PayloadOffset);
6849 for (unsigned i = 0; i < numArgs; ++i)
6850 addArgument(lowJSValue(m_graph.varArgChild(node, 1 + i)), virtualRegisterForArgument(i), 0);
6851
6852 PatchpointValue* patchpoint = m_out.patchpoint(Int64);
6853 patchpoint->appendVector(arguments);
6854
6855 RefPtr<PatchpointExceptionHandle> exceptionHandle = preparePatchpointForExceptions(patchpoint);
6856
6857 patchpoint->append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister));
6858 patchpoint->append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister));
6859 patchpoint->clobber(RegisterSet::macroScratchRegisters());
6860 patchpoint->clobberLate(RegisterSet::volatileRegistersForJSCall());
6861 patchpoint->resultConstraint = ValueRep::reg(GPRInfo::returnValueGPR);
6862
6863 CodeOrigin codeOrigin = codeOriginDescriptionOfCallSite();
6864 State* state = &m_ftlState;
6865 patchpoint->setGenerator(
6866 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
6867 AllowMacroScratchRegisterUsage allowScratch(jit);
6868 CallSiteIndex callSiteIndex = state->jitCode->common.addUniqueCallSiteIndex(codeOrigin);
6869
6870 Box<CCallHelpers::JumpList> exceptions = exceptionHandle->scheduleExitCreation(params)->jumps(jit);
6871
6872 exceptionHandle->scheduleExitCreationForUnwind(params, callSiteIndex);
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00006873
fpizlo@apple.com48bf58d2016-07-18 19:32:34 +00006874 jit.store32(
6875 CCallHelpers::TrustedImm32(callSiteIndex.bits()),
6876 CCallHelpers::tagFor(VirtualRegister(CallFrameSlot::argumentCount)));
6877
6878 CallLinkInfo* callLinkInfo = jit.codeBlock()->addCallLinkInfo();
commit-queue@webkit.org2cb9c252016-12-13 19:38:13 +00006879 callLinkInfo->setUpCall(CallLinkInfo::Call, node->origin.semantic, GPRInfo::regT0);
fpizlo@apple.com48bf58d2016-07-18 19:32:34 +00006880
6881 jit.addPtr(CCallHelpers::TrustedImm32(-static_cast<ptrdiff_t>(sizeof(CallerFrameAndPC))), CCallHelpers::stackPointerRegister, GPRInfo::regT1);
6882 jit.storePtr(GPRInfo::callFrameRegister, CCallHelpers::Address(GPRInfo::regT1, CallFrame::callerFrameOffset()));
6883
6884 // Now we need to make room for:
6885 // - The caller frame and PC for a call to operationCallEval.
6886 // - Potentially two arguments on the stack.
6887 unsigned requiredBytes = sizeof(CallerFrameAndPC) + sizeof(ExecState*) * 2;
6888 requiredBytes = WTF::roundUpToMultipleOf(stackAlignmentBytes(), requiredBytes);
6889 jit.subPtr(CCallHelpers::TrustedImm32(requiredBytes), CCallHelpers::stackPointerRegister);
6890 jit.setupArgumentsWithExecState(GPRInfo::regT1);
6891 jit.move(CCallHelpers::TrustedImmPtr(bitwise_cast<void*>(operationCallEval)), GPRInfo::nonPreservedNonArgumentGPR);
6892 jit.call(GPRInfo::nonPreservedNonArgumentGPR);
6893 exceptions->append(jit.emitExceptionCheck(AssemblyHelpers::NormalExceptionCheck, AssemblyHelpers::FarJumpWidth));
6894
6895 CCallHelpers::Jump done = jit.branchTest64(CCallHelpers::NonZero, GPRInfo::returnValueGPR);
6896
6897 jit.addPtr(CCallHelpers::TrustedImm32(requiredBytes), CCallHelpers::stackPointerRegister);
6898 jit.load64(CCallHelpers::calleeFrameSlot(CallFrameSlot::callee), GPRInfo::regT0);
6899 jit.emitDumbVirtualCall(callLinkInfo);
6900
6901 done.link(&jit);
6902 jit.addPtr(
6903 CCallHelpers::TrustedImm32(-params.proc().frameSize()),
6904 GPRInfo::callFrameRegister, CCallHelpers::stackPointerRegister);
6905 });
6906
6907 setJSValue(patchpoint);
6908 }
6909
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +00006910 void compileLoadVarargs()
6911 {
6912 LoadVarargsData* data = m_node->loadVarargsData();
6913 LValue jsArguments = lowJSValue(m_node->child1());
6914
6915 LValue length = vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00006916 Int32, m_out.operation(operationSizeOfVarargs), m_callFrame, jsArguments,
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +00006917 m_out.constInt32(data->offset));
6918
6919 // FIXME: There is a chance that we will call an effectful length property twice. This is safe
6920 // from the standpoint of the VM's integrity, but it's subtly wrong from a spec compliance
6921 // standpoint. The best solution would be one where we can exit *into* the op_call_varargs right
6922 // past the sizing.
6923 // https://bugs.webkit.org/show_bug.cgi?id=141448
6924
6925 LValue lengthIncludingThis = m_out.add(length, m_out.int32One);
6926 speculate(
6927 VarargsOverflow, noValue(), nullptr,
6928 m_out.above(lengthIncludingThis, m_out.constInt32(data->limit)));
6929
6930 m_out.store32(lengthIncludingThis, payloadFor(data->machineCount));
6931
6932 // FIXME: This computation is rather silly. If operationLaodVarargs just took a pointer instead
6933 // of a VirtualRegister, we wouldn't have to do this.
6934 // https://bugs.webkit.org/show_bug.cgi?id=141660
6935 LValue machineStart = m_out.lShr(
6936 m_out.sub(addressFor(data->machineStart.offset()).value(), m_callFrame),
6937 m_out.constIntPtr(3));
6938
6939 vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00006940 Void, m_out.operation(operationLoadVarargs), m_callFrame,
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +00006941 m_out.castToInt32(machineStart), jsArguments, m_out.constInt32(data->offset),
6942 length, m_out.constInt32(data->mandatoryMinimum));
6943 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00006944
6945 void compileForwardVarargs()
6946 {
sbarati@apple.come20444a2016-11-30 06:24:44 +00006947 if (m_node->child1() && m_node->child1()->op() == PhantomNewArrayWithSpread) {
6948 compileForwardVarargsWithSpread();
6949 return;
6950 }
6951
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00006952 LoadVarargsData* data = m_node->loadVarargsData();
keith_miller@apple.come497e202016-06-13 21:05:36 +00006953 InlineCallFrame* inlineCallFrame;
6954 if (m_node->child1())
6955 inlineCallFrame = m_node->child1()->origin.semantic.inlineCallFrame;
6956 else
6957 inlineCallFrame = m_node->origin.semantic.inlineCallFrame;
sbarati@apple.com7a74ce72016-11-01 20:03:03 +00006958
6959 LValue length = nullptr;
6960 LValue lengthIncludingThis = nullptr;
6961 ArgumentsLength argumentsLength = getArgumentsLength(inlineCallFrame);
6962 if (argumentsLength.isKnown) {
6963 unsigned knownLength = argumentsLength.known;
6964 if (knownLength >= data->offset)
6965 knownLength = knownLength - data->offset;
6966 else
6967 knownLength = 0;
6968 length = m_out.constInt32(knownLength);
6969 lengthIncludingThis = m_out.constInt32(knownLength + 1);
6970 } else {
6971 // We need to perform the same logical operation as the code above, but through dynamic operations.
6972 if (!data->offset)
6973 length = argumentsLength.value;
6974 else {
6975 LBasicBlock isLarger = m_out.newBlock();
6976 LBasicBlock continuation = m_out.newBlock();
6977
6978 ValueFromBlock smallerOrEqualLengthResult = m_out.anchor(m_out.constInt32(0));
6979 m_out.branch(
6980 m_out.above(argumentsLength.value, m_out.constInt32(data->offset)), unsure(isLarger), unsure(continuation));
6981 LBasicBlock lastNext = m_out.appendTo(isLarger, continuation);
6982 ValueFromBlock largerLengthResult = m_out.anchor(m_out.sub(argumentsLength.value, m_out.constInt32(data->offset)));
6983 m_out.jump(continuation);
6984
6985 m_out.appendTo(continuation, lastNext);
6986 length = m_out.phi(Int32, smallerOrEqualLengthResult, largerLengthResult);
6987 }
6988 lengthIncludingThis = m_out.add(length, m_out.constInt32(1));
6989 }
6990
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00006991 speculate(
6992 VarargsOverflow, noValue(), nullptr,
6993 m_out.above(lengthIncludingThis, m_out.constInt32(data->limit)));
6994
6995 m_out.store32(lengthIncludingThis, payloadFor(data->machineCount));
6996
sbarati@apple.com7a74ce72016-11-01 20:03:03 +00006997 unsigned numberOfArgumentsToSkip = data->offset;
6998 LValue sourceStart = getArgumentsStart(inlineCallFrame, numberOfArgumentsToSkip);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00006999 LValue targetStart = addressFor(data->machineStart).value();
7000
fpizlo@apple.com91331742016-03-07 02:07:28 +00007001 LBasicBlock undefinedLoop = m_out.newBlock();
7002 LBasicBlock mainLoopEntry = m_out.newBlock();
7003 LBasicBlock mainLoop = m_out.newBlock();
7004 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00007005
7006 LValue lengthAsPtr = m_out.zeroExtPtr(length);
fpizlo@apple.com373ed6b2015-12-15 04:52:55 +00007007 LValue loopBoundValue = m_out.constIntPtr(data->mandatoryMinimum);
7008 ValueFromBlock loopBound = m_out.anchor(loopBoundValue);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00007009 m_out.branch(
fpizlo@apple.com373ed6b2015-12-15 04:52:55 +00007010 m_out.above(loopBoundValue, lengthAsPtr), unsure(undefinedLoop), unsure(mainLoopEntry));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00007011
7012 LBasicBlock lastNext = m_out.appendTo(undefinedLoop, mainLoopEntry);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00007013 LValue previousIndex = m_out.phi(pointerType(), loopBound);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00007014 LValue currentIndex = m_out.sub(previousIndex, m_out.intPtrOne);
7015 m_out.store64(
7016 m_out.constInt64(JSValue::encode(jsUndefined())),
7017 m_out.baseIndex(m_heaps.variables, targetStart, currentIndex));
7018 ValueFromBlock nextIndex = m_out.anchor(currentIndex);
benjamin@webkit.org81ec96c2015-11-18 23:14:54 +00007019 m_out.addIncomingToPhi(previousIndex, nextIndex);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00007020 m_out.branch(
7021 m_out.above(currentIndex, lengthAsPtr), unsure(undefinedLoop), unsure(mainLoopEntry));
7022
7023 m_out.appendTo(mainLoopEntry, mainLoop);
7024 loopBound = m_out.anchor(lengthAsPtr);
fpizlo@apple.com373ed6b2015-12-15 04:52:55 +00007025 m_out.branch(m_out.notNull(lengthAsPtr), unsure(mainLoop), unsure(continuation));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00007026
7027 m_out.appendTo(mainLoop, continuation);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00007028 previousIndex = m_out.phi(pointerType(), loopBound);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00007029 currentIndex = m_out.sub(previousIndex, m_out.intPtrOne);
7030 LValue value = m_out.load64(
sbarati@apple.com7a74ce72016-11-01 20:03:03 +00007031 m_out.baseIndex(m_heaps.variables, sourceStart, currentIndex));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00007032 m_out.store64(value, m_out.baseIndex(m_heaps.variables, targetStart, currentIndex));
7033 nextIndex = m_out.anchor(currentIndex);
benjamin@webkit.org81ec96c2015-11-18 23:14:54 +00007034 m_out.addIncomingToPhi(previousIndex, nextIndex);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00007035 m_out.branch(m_out.isNull(currentIndex), unsure(continuation), unsure(mainLoop));
7036
7037 m_out.appendTo(continuation, lastNext);
7038 }
fpizlo@apple.comff27eed2014-07-23 04:33:37 +00007039
sbarati@apple.come20444a2016-11-30 06:24:44 +00007040 LValue getSpreadLengthFromInlineCallFrame(InlineCallFrame* inlineCallFrame, unsigned numberOfArgumentsToSkip)
7041 {
7042 ArgumentsLength argumentsLength = getArgumentsLength(inlineCallFrame);
7043 if (argumentsLength.isKnown) {
7044 unsigned knownLength = argumentsLength.known;
7045 if (knownLength >= numberOfArgumentsToSkip)
7046 knownLength = knownLength - numberOfArgumentsToSkip;
7047 else
7048 knownLength = 0;
7049 return m_out.constInt32(knownLength);
7050 }
7051
7052
7053 // We need to perform the same logical operation as the code above, but through dynamic operations.
7054 if (!numberOfArgumentsToSkip)
7055 return argumentsLength.value;
7056
7057 LBasicBlock isLarger = m_out.newBlock();
7058 LBasicBlock continuation = m_out.newBlock();
7059
7060 ValueFromBlock smallerOrEqualLengthResult = m_out.anchor(m_out.constInt32(0));
7061 m_out.branch(
7062 m_out.above(argumentsLength.value, m_out.constInt32(numberOfArgumentsToSkip)), unsure(isLarger), unsure(continuation));
7063 LBasicBlock lastNext = m_out.appendTo(isLarger, continuation);
7064 ValueFromBlock largerLengthResult = m_out.anchor(m_out.sub(argumentsLength.value, m_out.constInt32(numberOfArgumentsToSkip)));
7065 m_out.jump(continuation);
7066
7067 m_out.appendTo(continuation, lastNext);
7068 return m_out.phi(Int32, smallerOrEqualLengthResult, largerLengthResult);
7069 }
7070
7071 void compileForwardVarargsWithSpread()
7072 {
7073 HashMap<InlineCallFrame*, LValue, WTF::DefaultHash<InlineCallFrame*>::Hash, WTF::NullableHashTraits<InlineCallFrame*>> cachedSpreadLengths;
7074
7075 Node* arrayWithSpread = m_node->child1().node();
7076 RELEASE_ASSERT(arrayWithSpread->op() == PhantomNewArrayWithSpread);
7077 BitVector* bitVector = arrayWithSpread->bitVector();
7078
7079 unsigned numberOfStaticArguments = 0;
7080 Vector<LValue, 2> spreadLengths;
7081 for (unsigned i = 0; i < arrayWithSpread->numChildren(); i++) {
7082 if (bitVector->get(i)) {
7083 Node* child = m_graph.varArgChild(arrayWithSpread, i).node();
7084 ASSERT(child->op() == PhantomSpread);
7085 ASSERT(child->child1()->op() == PhantomCreateRest);
7086 InlineCallFrame* inlineCallFrame = child->child1()->origin.semantic.inlineCallFrame;
7087 LValue length = cachedSpreadLengths.ensure(inlineCallFrame, [&] () {
7088 return getSpreadLengthFromInlineCallFrame(inlineCallFrame, child->child1()->numberOfArgumentsToSkip());
7089 }).iterator->value;
7090 spreadLengths.append(length);
7091 } else
7092 ++numberOfStaticArguments;
7093 }
7094
7095 LValue lengthIncludingThis = m_out.constInt32(1 + numberOfStaticArguments);
7096 for (LValue length : spreadLengths)
7097 lengthIncludingThis = m_out.add(lengthIncludingThis, length);
7098
7099 LoadVarargsData* data = m_node->loadVarargsData();
7100 speculate(
7101 VarargsOverflow, noValue(), nullptr,
7102 m_out.above(lengthIncludingThis, m_out.constInt32(data->limit)));
7103
7104 m_out.store32(lengthIncludingThis, payloadFor(data->machineCount));
7105
7106 LValue targetStart = addressFor(data->machineStart).value();
7107 LValue storeIndex = m_out.constIntPtr(0);
7108 for (unsigned i = 0; i < arrayWithSpread->numChildren(); i++) {
7109 if (bitVector->get(i)) {
7110 Node* child = m_graph.varArgChild(arrayWithSpread, i).node();
7111 RELEASE_ASSERT(child->op() == PhantomSpread);
7112 RELEASE_ASSERT(child->child1()->op() == PhantomCreateRest);
7113 InlineCallFrame* inlineCallFrame = child->child1()->origin.semantic.inlineCallFrame;
7114
7115 LValue sourceStart = getArgumentsStart(inlineCallFrame, child->child1()->numberOfArgumentsToSkip());
7116 LValue spreadLength = m_out.zeroExtPtr(cachedSpreadLengths.get(inlineCallFrame));
7117
7118 LBasicBlock loop = m_out.newBlock();
7119 LBasicBlock continuation = m_out.newBlock();
7120 ValueFromBlock startLoadIndex = m_out.anchor(m_out.constIntPtr(0));
7121 ValueFromBlock startStoreIndex = m_out.anchor(storeIndex);
7122 ValueFromBlock startStoreIndexForEnd = m_out.anchor(storeIndex);
7123
7124 m_out.branch(m_out.isZero64(spreadLength), unsure(continuation), unsure(loop));
7125
7126 LBasicBlock lastNext = m_out.appendTo(loop, continuation);
7127 LValue loopStoreIndex = m_out.phi(Int64, startStoreIndex);
7128 LValue loadIndex = m_out.phi(Int64, startLoadIndex);
7129 LValue value = m_out.load64(
7130 m_out.baseIndex(m_heaps.variables, sourceStart, loadIndex));
7131 m_out.store64(value, m_out.baseIndex(m_heaps.variables, targetStart, loopStoreIndex));
7132 LValue nextLoadIndex = m_out.add(m_out.constIntPtr(1), loadIndex);
7133 m_out.addIncomingToPhi(loadIndex, m_out.anchor(nextLoadIndex));
7134 LValue nextStoreIndex = m_out.add(m_out.constIntPtr(1), loopStoreIndex);
7135 m_out.addIncomingToPhi(loopStoreIndex, m_out.anchor(nextStoreIndex));
7136 ValueFromBlock loopStoreIndexForEnd = m_out.anchor(nextStoreIndex);
7137 m_out.branch(m_out.below(nextLoadIndex, spreadLength), unsure(loop), unsure(continuation));
7138
7139 m_out.appendTo(continuation, lastNext);
7140 storeIndex = m_out.phi(Int64, startStoreIndexForEnd, loopStoreIndexForEnd);
7141 } else {
7142 LValue value = lowJSValue(m_graph.varArgChild(arrayWithSpread, i));
7143 m_out.store64(value, m_out.baseIndex(m_heaps.variables, targetStart, storeIndex));
7144 storeIndex = m_out.add(m_out.constIntPtr(1), storeIndex);
7145 }
7146 }
7147
7148 LBasicBlock undefinedLoop = m_out.newBlock();
7149 LBasicBlock continuation = m_out.newBlock();
7150
7151 ValueFromBlock startStoreIndex = m_out.anchor(storeIndex);
7152 LValue loopBoundValue = m_out.constIntPtr(data->mandatoryMinimum);
7153 m_out.branch(m_out.below(storeIndex, loopBoundValue),
7154 unsure(undefinedLoop), unsure(continuation));
7155
7156 LBasicBlock lastNext = m_out.appendTo(undefinedLoop, continuation);
7157 LValue loopStoreIndex = m_out.phi(Int64, startStoreIndex);
7158 m_out.store64(
7159 m_out.constInt64(JSValue::encode(jsUndefined())),
7160 m_out.baseIndex(m_heaps.variables, targetStart, loopStoreIndex));
7161 LValue nextIndex = m_out.add(loopStoreIndex, m_out.constIntPtr(1));
7162 m_out.addIncomingToPhi(loopStoreIndex, m_out.anchor(nextIndex));
7163 m_out.branch(
7164 m_out.below(nextIndex, loopBoundValue), unsure(undefinedLoop), unsure(continuation));
7165
7166 m_out.appendTo(continuation, lastNext);
7167 }
7168
oliver@apple.com0d018be2013-07-25 04:00:02 +00007169 void compileJump()
7170 {
fpizlo@apple.comb8377cd2014-02-20 08:00:28 +00007171 m_out.jump(lowBlock(m_node->targetBlock()));
oliver@apple.com0d018be2013-07-25 04:00:02 +00007172 }
7173
oliver@apple.comea771492013-07-25 03:58:38 +00007174 void compileBranch()
7175 {
oliver@apple.comec61ab22013-07-25 04:01:02 +00007176 m_out.branch(
7177 boolify(m_node->child1()),
fpizlo@apple.comb8377cd2014-02-20 08:00:28 +00007178 WeightedTarget(
7179 lowBlock(m_node->branchData()->taken.block),
7180 m_node->branchData()->taken.count),
7181 WeightedTarget(
7182 lowBlock(m_node->branchData()->notTaken.block),
7183 m_node->branchData()->notTaken.count));
oliver@apple.comea771492013-07-25 03:58:38 +00007184 }
7185
oliver@apple.com9f4a6722013-07-25 04:03:05 +00007186 void compileSwitch()
7187 {
7188 SwitchData* data = m_node->switchData();
7189 switch (data->kind) {
7190 case SwitchImm: {
7191 Vector<ValueFromBlock, 2> intValues;
fpizlo@apple.com91331742016-03-07 02:07:28 +00007192 LBasicBlock switchOnInts = m_out.newBlock();
oliver@apple.com9f4a6722013-07-25 04:03:05 +00007193
7194 LBasicBlock lastNext = m_out.appendTo(m_out.m_block, switchOnInts);
7195
7196 switch (m_node->child1().useKind()) {
7197 case Int32Use: {
7198 intValues.append(m_out.anchor(lowInt32(m_node->child1())));
7199 m_out.jump(switchOnInts);
7200 break;
7201 }
7202
7203 case UntypedUse: {
fpizlo@apple.com91331742016-03-07 02:07:28 +00007204 LBasicBlock isInt = m_out.newBlock();
7205 LBasicBlock isNotInt = m_out.newBlock();
7206 LBasicBlock isDouble = m_out.newBlock();
oliver@apple.com9f4a6722013-07-25 04:03:05 +00007207
7208 LValue boxedValue = lowJSValue(m_node->child1());
fpizlo@apple.com975ae502014-02-19 22:29:43 +00007209 m_out.branch(isNotInt32(boxedValue), unsure(isNotInt), unsure(isInt));
oliver@apple.com9f4a6722013-07-25 04:03:05 +00007210
7211 LBasicBlock innerLastNext = m_out.appendTo(isInt, isNotInt);
7212
7213 intValues.append(m_out.anchor(unboxInt32(boxedValue)));
7214 m_out.jump(switchOnInts);
7215
7216 m_out.appendTo(isNotInt, isDouble);
7217 m_out.branch(
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00007218 isCellOrMisc(boxedValue, provenType(m_node->child1())),
fpizlo@apple.comb8377cd2014-02-20 08:00:28 +00007219 usually(lowBlock(data->fallThrough.block)), rarely(isDouble));
oliver@apple.com9f4a6722013-07-25 04:03:05 +00007220
7221 m_out.appendTo(isDouble, innerLastNext);
7222 LValue doubleValue = unboxDouble(boxedValue);
fpizlo@apple.comdae23fb2015-12-21 20:54:51 +00007223 LValue intInDouble = m_out.doubleToInt(doubleValue);
oliver@apple.com9f4a6722013-07-25 04:03:05 +00007224 intValues.append(m_out.anchor(intInDouble));
7225 m_out.branch(
7226 m_out.doubleEqual(m_out.intToDouble(intInDouble), doubleValue),
fpizlo@apple.comb8377cd2014-02-20 08:00:28 +00007227 unsure(switchOnInts), unsure(lowBlock(data->fallThrough.block)));
oliver@apple.com9f4a6722013-07-25 04:03:05 +00007228 break;
7229 }
7230
7231 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00007232 DFG_CRASH(m_graph, m_node, "Bad use kind");
7233 break;
oliver@apple.com9f4a6722013-07-25 04:03:05 +00007234 }
7235
7236 m_out.appendTo(switchOnInts, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00007237 buildSwitch(data, Int32, m_out.phi(Int32, intValues));
oliver@apple.com9f4a6722013-07-25 04:03:05 +00007238 return;
oliver@apple.com9e1c8092013-07-25 04:03:16 +00007239 }
7240
oliver@apple.com39478942013-07-25 04:03:18 +00007241 case SwitchChar: {
7242 LValue stringValue;
7243
fpizlo@apple.comb8377cd2014-02-20 08:00:28 +00007244 // FIXME: We should use something other than unsure() for the branch weight
7245 // of the fallThrough block. The main challenge is just that we have multiple
7246 // branches to fallThrough but a single count, so we would need to divvy it up
7247 // among the different lowered branches.
7248 // https://bugs.webkit.org/show_bug.cgi?id=129082
7249
oliver@apple.com39478942013-07-25 04:03:18 +00007250 switch (m_node->child1().useKind()) {
7251 case StringUse: {
7252 stringValue = lowString(m_node->child1());
7253 break;
7254 }
7255
7256 case UntypedUse: {
7257 LValue unboxedValue = lowJSValue(m_node->child1());
7258
fpizlo@apple.com91331742016-03-07 02:07:28 +00007259 LBasicBlock isCellCase = m_out.newBlock();
7260 LBasicBlock isStringCase = m_out.newBlock();
oliver@apple.com39478942013-07-25 04:03:18 +00007261
7262 m_out.branch(
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00007263 isNotCell(unboxedValue, provenType(m_node->child1())),
fpizlo@apple.comb8377cd2014-02-20 08:00:28 +00007264 unsure(lowBlock(data->fallThrough.block)), unsure(isCellCase));
oliver@apple.com39478942013-07-25 04:03:18 +00007265
7266 LBasicBlock lastNext = m_out.appendTo(isCellCase, isStringCase);
7267 LValue cellValue = unboxedValue;
fpizlo@apple.com975ae502014-02-19 22:29:43 +00007268 m_out.branch(
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00007269 isNotString(cellValue, provenType(m_node->child1())),
fpizlo@apple.comb8377cd2014-02-20 08:00:28 +00007270 unsure(lowBlock(data->fallThrough.block)), unsure(isStringCase));
oliver@apple.com39478942013-07-25 04:03:18 +00007271
7272 m_out.appendTo(isStringCase, lastNext);
7273 stringValue = cellValue;
7274 break;
7275 }
7276
7277 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00007278 DFG_CRASH(m_graph, m_node, "Bad use kind");
7279 break;
oliver@apple.com39478942013-07-25 04:03:18 +00007280 }
7281
fpizlo@apple.com91331742016-03-07 02:07:28 +00007282 LBasicBlock lengthIs1 = m_out.newBlock();
7283 LBasicBlock needResolution = m_out.newBlock();
7284 LBasicBlock resolved = m_out.newBlock();
7285 LBasicBlock is8Bit = m_out.newBlock();
7286 LBasicBlock is16Bit = m_out.newBlock();
7287 LBasicBlock continuation = m_out.newBlock();
oliver@apple.com39478942013-07-25 04:03:18 +00007288
7289 m_out.branch(
7290 m_out.notEqual(
msaboff@apple.com95894332014-01-29 19:18:54 +00007291 m_out.load32NonNegative(stringValue, m_heaps.JSString_length),
oliver@apple.com39478942013-07-25 04:03:18 +00007292 m_out.int32One),
fpizlo@apple.comb8377cd2014-02-20 08:00:28 +00007293 unsure(lowBlock(data->fallThrough.block)), unsure(lengthIs1));
oliver@apple.com39478942013-07-25 04:03:18 +00007294
7295 LBasicBlock lastNext = m_out.appendTo(lengthIs1, needResolution);
7296 Vector<ValueFromBlock, 2> values;
7297 LValue fastValue = m_out.loadPtr(stringValue, m_heaps.JSString_value);
7298 values.append(m_out.anchor(fastValue));
fpizlo@apple.com975ae502014-02-19 22:29:43 +00007299 m_out.branch(m_out.isNull(fastValue), rarely(needResolution), usually(resolved));
oliver@apple.com39478942013-07-25 04:03:18 +00007300
7301 m_out.appendTo(needResolution, resolved);
7302 values.append(m_out.anchor(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00007303 vmCall(pointerType(), m_out.operation(operationResolveRope), m_callFrame, stringValue)));
oliver@apple.com39478942013-07-25 04:03:18 +00007304 m_out.jump(resolved);
7305
7306 m_out.appendTo(resolved, is8Bit);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00007307 LValue value = m_out.phi(pointerType(), values);
oliver@apple.com39478942013-07-25 04:03:18 +00007308 LValue characterData = m_out.loadPtr(value, m_heaps.StringImpl_data);
7309 m_out.branch(
7310 m_out.testNonZero32(
7311 m_out.load32(value, m_heaps.StringImpl_hashAndFlags),
7312 m_out.constInt32(StringImpl::flagIs8Bit())),
fpizlo@apple.com975ae502014-02-19 22:29:43 +00007313 unsure(is8Bit), unsure(is16Bit));
oliver@apple.com39478942013-07-25 04:03:18 +00007314
7315 Vector<ValueFromBlock, 2> characters;
7316 m_out.appendTo(is8Bit, is16Bit);
benjamin@webkit.org2e864d22015-11-17 06:20:21 +00007317 characters.append(m_out.anchor(m_out.load8ZeroExt32(characterData, m_heaps.characters8[0])));
oliver@apple.com39478942013-07-25 04:03:18 +00007318 m_out.jump(continuation);
7319
7320 m_out.appendTo(is16Bit, continuation);
benjamin@webkit.org2e864d22015-11-17 06:20:21 +00007321 characters.append(m_out.anchor(m_out.load16ZeroExt32(characterData, m_heaps.characters16[0])));
oliver@apple.com39478942013-07-25 04:03:18 +00007322 m_out.jump(continuation);
7323
7324 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00007325 buildSwitch(data, Int32, m_out.phi(Int32, characters));
oliver@apple.com9e1c8092013-07-25 04:03:16 +00007326 return;
oliver@apple.com5c826c02013-07-25 04:03:51 +00007327 }
7328
fpizlo@apple.com29abafe2014-08-28 19:09:48 +00007329 case SwitchString: {
fpizlo@apple.com5a3036b2015-04-29 03:34:43 +00007330 switch (m_node->child1().useKind()) {
7331 case StringIdentUse: {
7332 LValue stringImpl = lowStringIdent(m_node->child1());
7333
7334 Vector<SwitchCase> cases;
7335 for (unsigned i = 0; i < data->cases.size(); ++i) {
7336 LValue value = m_out.constIntPtr(data->cases[i].value.stringImpl());
7337 LBasicBlock block = lowBlock(data->cases[i].target.block);
7338 Weight weight = Weight(data->cases[i].target.count);
7339 cases.append(SwitchCase(value, block, weight));
7340 }
7341
7342 m_out.switchInstruction(
7343 stringImpl, cases, lowBlock(data->fallThrough.block),
7344 Weight(data->fallThrough.count));
7345 return;
7346 }
7347
7348 case StringUse: {
7349 switchString(data, lowString(m_node->child1()));
7350 return;
7351 }
7352
7353 case UntypedUse: {
7354 LValue value = lowJSValue(m_node->child1());
7355
fpizlo@apple.com91331742016-03-07 02:07:28 +00007356 LBasicBlock isCellBlock = m_out.newBlock();
7357 LBasicBlock isStringBlock = m_out.newBlock();
fpizlo@apple.com5a3036b2015-04-29 03:34:43 +00007358
7359 m_out.branch(
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00007360 isCell(value, provenType(m_node->child1())),
7361 unsure(isCellBlock), unsure(lowBlock(data->fallThrough.block)));
fpizlo@apple.com5a3036b2015-04-29 03:34:43 +00007362
7363 LBasicBlock lastNext = m_out.appendTo(isCellBlock, isStringBlock);
7364
7365 m_out.branch(
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00007366 isString(value, provenType(m_node->child1())),
fpizlo@apple.com5a3036b2015-04-29 03:34:43 +00007367 unsure(isStringBlock), unsure(lowBlock(data->fallThrough.block)));
7368
7369 m_out.appendTo(isStringBlock, lastNext);
7370
7371 switchString(data, value);
7372 return;
7373 }
7374
7375 default:
7376 DFG_CRASH(m_graph, m_node, "Bad use kind");
7377 return;
7378 }
fpizlo@apple.com29abafe2014-08-28 19:09:48 +00007379 return;
oliver@apple.com5c826c02013-07-25 04:03:51 +00007380 }
fpizlo@apple.com29abafe2014-08-28 19:09:48 +00007381
7382 case SwitchCell: {
7383 LValue cell;
7384 switch (m_node->child1().useKind()) {
7385 case CellUse: {
7386 cell = lowCell(m_node->child1());
7387 break;
7388 }
7389
7390 case UntypedUse: {
7391 LValue value = lowJSValue(m_node->child1());
fpizlo@apple.com91331742016-03-07 02:07:28 +00007392 LBasicBlock cellCase = m_out.newBlock();
fpizlo@apple.com29abafe2014-08-28 19:09:48 +00007393 m_out.branch(
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00007394 isCell(value, provenType(m_node->child1())),
7395 unsure(cellCase), unsure(lowBlock(data->fallThrough.block)));
fpizlo@apple.com29abafe2014-08-28 19:09:48 +00007396 m_out.appendTo(cellCase);
7397 cell = value;
7398 break;
7399 }
7400
7401 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00007402 DFG_CRASH(m_graph, m_node, "Bad use kind");
fpizlo@apple.com29abafe2014-08-28 19:09:48 +00007403 return;
7404 }
7405
fpizlo@apple.com994d4532016-07-03 19:34:55 +00007406 buildSwitch(m_node->switchData(), pointerType(), cell);
fpizlo@apple.com29abafe2014-08-28 19:09:48 +00007407 return;
7408 } }
oliver@apple.com39478942013-07-25 04:03:18 +00007409
msaboff@apple.com044ba8d2015-02-18 23:52:16 +00007410 DFG_CRASH(m_graph, m_node, "Bad switch kind");
oliver@apple.com9f4a6722013-07-25 04:03:05 +00007411 }
7412
oliver@apple.com0d018be2013-07-25 04:00:02 +00007413 void compileReturn()
7414 {
oliver@apple.com0d018be2013-07-25 04:00:02 +00007415 m_out.ret(lowJSValue(m_node->child1()));
7416 }
7417
7418 void compileForceOSRExit()
7419 {
7420 terminate(InadequateCoverage);
7421 }
7422
fpizlo@apple.come079bb52014-03-05 07:41:03 +00007423 void compileThrow()
7424 {
7425 terminate(Uncountable);
7426 }
7427
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00007428 void compileInvalidationPoint()
7429 {
fpizlo@apple.comed46a0b2013-10-31 22:49:51 +00007430 if (verboseCompilationEnabled())
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00007431 dataLog(" Invalidation point with availability: ", availabilityMap(), "\n");
fpizlo@apple.comf29186e2015-08-26 19:24:41 +00007432
7433 DFG_ASSERT(m_graph, m_node, m_origin.exitOK);
fpizlo@apple.comed46a0b2013-10-31 22:49:51 +00007434
fpizlo@apple.com203ebdb2015-12-21 18:56:54 +00007435 PatchpointValue* patchpoint = m_out.patchpoint(Void);
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +00007436 OSRExitDescriptor* descriptor = appendOSRExitDescriptor(noValue(), nullptr);
7437 NodeOrigin origin = m_origin;
7438 patchpoint->appendColdAnys(buildExitArguments(descriptor, origin.forExit, noValue()));
7439
7440 State* state = &m_ftlState;
7441
7442 patchpoint->setGenerator(
7443 [=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
7444 // The MacroAssembler knows more about this than B3 does. The watchpointLabel() method
7445 // will ensure that this is followed by a nop shadow but only when this is actually
7446 // necessary.
7447 CCallHelpers::Label label = jit.watchpointLabel();
7448
7449 RefPtr<OSRExitHandle> handle = descriptor->emitOSRExitLater(
7450 *state, UncountableInvalidation, origin, params);
7451
7452 RefPtr<JITCode> jitCode = state->jitCode.get();
7453
7454 jit.addLinkTask(
7455 [=] (LinkBuffer& linkBuffer) {
7456 JumpReplacement jumpReplacement(
7457 linkBuffer.locationOf(label),
7458 linkBuffer.locationOf(handle->label));
7459 jitCode->common.jumpReplacements.append(jumpReplacement);
7460 });
7461 });
7462
7463 // Set some obvious things.
7464 patchpoint->effects.terminal = false;
fpizlo@apple.comdb423142016-02-02 23:21:12 +00007465 patchpoint->effects.writesLocalState = false;
7466 patchpoint->effects.readsLocalState = false;
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +00007467
7468 // This is how we tell B3 about the possibility of jump replacement.
7469 patchpoint->effects.exitsSideways = true;
7470
7471 // It's not possible for some prior branch to determine the safety of this operation. It's always
7472 // fine to execute this on some path that wouldn't have originally executed it before
7473 // optimization.
7474 patchpoint->effects.controlDependent = false;
7475
7476 // If this falls through then it won't write anything.
7477 patchpoint->effects.writes = HeapRange();
7478
7479 // When this abruptly terminates, it could read any heap location.
7480 patchpoint->effects.reads = HeapRange::top();
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00007481 }
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +00007482
7483 void compileIsEmpty()
7484 {
7485 setBoolean(m_out.isZero64(lowJSValue(m_node->child1())));
7486 }
fpizlo@apple.comd84425d2013-10-30 19:58:08 +00007487
fpizlo@apple.com40750682014-03-13 22:18:50 +00007488 void compileIsUndefined()
7489 {
7490 setBoolean(equalNullOrUndefined(m_node->child1(), AllCellsAreFalse, EqualUndefined));
7491 }
7492
7493 void compileIsBoolean()
7494 {
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00007495 setBoolean(isBoolean(lowJSValue(m_node->child1()), provenType(m_node->child1())));
fpizlo@apple.com40750682014-03-13 22:18:50 +00007496 }
7497
7498 void compileIsNumber()
7499 {
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00007500 setBoolean(isNumber(lowJSValue(m_node->child1()), provenType(m_node->child1())));
fpizlo@apple.com40750682014-03-13 22:18:50 +00007501 }
7502
utatane.tea@gmail.com4a748b12016-09-17 06:32:50 +00007503 void compileIsCellWithType()
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +00007504 {
utatane.tea@gmail.com4a748b12016-09-17 06:32:50 +00007505 if (m_node->child1().useKind() == UntypedUse) {
7506 LValue value = lowJSValue(m_node->child1());
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +00007507
utatane.tea@gmail.com4a748b12016-09-17 06:32:50 +00007508 LBasicBlock isCellCase = m_out.newBlock();
7509 LBasicBlock continuation = m_out.newBlock();
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +00007510
utatane.tea@gmail.com4a748b12016-09-17 06:32:50 +00007511 ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse);
7512 m_out.branch(
7513 isCell(value, provenType(m_node->child1())), unsure(isCellCase), unsure(continuation));
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +00007514
utatane.tea@gmail.com4a748b12016-09-17 06:32:50 +00007515 LBasicBlock lastNext = m_out.appendTo(isCellCase, continuation);
7516 ValueFromBlock cellResult = m_out.anchor(isCellWithType(value, m_node->queriedType(), m_node->speculatedTypeForQuery(), provenType(m_node->child1())));
7517 m_out.jump(continuation);
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +00007518
utatane.tea@gmail.com4a748b12016-09-17 06:32:50 +00007519 m_out.appendTo(continuation, lastNext);
7520 setBoolean(m_out.phi(Int32, notCellResult, cellResult));
7521 } else {
7522 ASSERT(m_node->child1().useKind() == CellUse);
7523 setBoolean(isCellWithType(lowCell(m_node->child1()), m_node->queriedType(), m_node->speculatedTypeForQuery(), provenType(m_node->child1())));
7524 }
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +00007525 }
7526
fpizlo@apple.com40750682014-03-13 22:18:50 +00007527 void compileIsObject()
7528 {
utatane.tea@gmail.com0bfb74c2015-02-24 23:01:58 +00007529 LValue value = lowJSValue(m_node->child1());
7530
fpizlo@apple.com91331742016-03-07 02:07:28 +00007531 LBasicBlock isCellCase = m_out.newBlock();
7532 LBasicBlock continuation = m_out.newBlock();
utatane.tea@gmail.com0bfb74c2015-02-24 23:01:58 +00007533
7534 ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse);
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00007535 m_out.branch(
7536 isCell(value, provenType(m_node->child1())), unsure(isCellCase), unsure(continuation));
utatane.tea@gmail.com0bfb74c2015-02-24 23:01:58 +00007537
7538 LBasicBlock lastNext = m_out.appendTo(isCellCase, continuation);
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00007539 ValueFromBlock cellResult = m_out.anchor(isObject(value, provenType(m_node->child1())));
utatane.tea@gmail.com0bfb74c2015-02-24 23:01:58 +00007540 m_out.jump(continuation);
7541
7542 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00007543 setBoolean(m_out.phi(Int32, notCellResult, cellResult));
utatane.tea@gmail.com0bfb74c2015-02-24 23:01:58 +00007544 }
7545
sbarati@apple.comeda65b82016-10-03 20:49:34 +00007546 LValue wangsInt64Hash(LValue input)
sbarati@apple.com21fc86e2016-09-06 23:22:01 +00007547 {
sbarati@apple.com21fc86e2016-09-06 23:22:01 +00007548 // key += ~(key << 32);
sbarati@apple.comeda65b82016-10-03 20:49:34 +00007549 LValue key = input;
sbarati@apple.com21fc86e2016-09-06 23:22:01 +00007550 LValue temp = key;
7551 temp = m_out.shl(temp, m_out.constInt32(32));
7552 temp = m_out.bitNot(temp);
7553 key = m_out.add(key, temp);
7554 // key ^= (key >> 22);
7555 temp = key;
7556 temp = m_out.lShr(temp, m_out.constInt32(22));
7557 key = m_out.bitXor(key, temp);
7558 // key += ~(key << 13);
7559 temp = key;
7560 temp = m_out.shl(temp, m_out.constInt32(13));
7561 temp = m_out.bitNot(temp);
7562 key = m_out.add(key, temp);
7563 // key ^= (key >> 8);
7564 temp = key;
7565 temp = m_out.lShr(temp, m_out.constInt32(8));
7566 key = m_out.bitXor(key, temp);
7567 // key += (key << 3);
7568 temp = key;
7569 temp = m_out.shl(temp, m_out.constInt32(3));
7570 key = m_out.add(key, temp);
7571 // key ^= (key >> 15);
7572 temp = key;
7573 temp = m_out.lShr(temp, m_out.constInt32(15));
7574 key = m_out.bitXor(key, temp);
7575 // key += ~(key << 27);
7576 temp = key;
7577 temp = m_out.shl(temp, m_out.constInt32(27));
7578 temp = m_out.bitNot(temp);
7579 key = m_out.add(key, temp);
7580 // key ^= (key >> 31);
7581 temp = key;
7582 temp = m_out.lShr(temp, m_out.constInt32(31));
7583 key = m_out.bitXor(key, temp);
7584 key = m_out.castToInt32(key);
7585
sbarati@apple.comeda65b82016-10-03 20:49:34 +00007586 return key;
7587 }
7588
7589 LValue mapHashString(LValue string)
7590 {
7591 LBasicBlock nonEmptyStringCase = m_out.newBlock();
7592 LBasicBlock slowCase = m_out.newBlock();
7593 LBasicBlock continuation = m_out.newBlock();
7594
7595 LValue stringImpl = m_out.loadPtr(string, m_heaps.JSString_value);
7596 m_out.branch(
7597 m_out.equal(stringImpl, m_out.constIntPtr(0)), unsure(slowCase), unsure(nonEmptyStringCase));
7598
7599 LBasicBlock lastNext = m_out.appendTo(nonEmptyStringCase, slowCase);
7600 LValue hash = m_out.lShr(m_out.load32(stringImpl, m_heaps.StringImpl_hashAndFlags), m_out.constInt32(StringImpl::s_flagCount));
7601 ValueFromBlock nonEmptyStringHashResult = m_out.anchor(hash);
7602 m_out.branch(m_out.equal(hash, m_out.constInt32(0)),
7603 unsure(slowCase), unsure(continuation));
7604
7605 m_out.appendTo(slowCase, continuation);
7606 ValueFromBlock slowResult = m_out.anchor(
7607 vmCall(Int32, m_out.operation(operationMapHash), m_callFrame, string));
7608 m_out.jump(continuation);
7609
7610 m_out.appendTo(continuation, lastNext);
7611 return m_out.phi(Int32, slowResult, nonEmptyStringHashResult);
7612 }
7613
7614 void compileMapHash()
7615 {
7616 switch (m_node->child1().useKind()) {
7617 case BooleanUse:
7618 case Int32Use:
7619 case SymbolUse:
7620 case ObjectUse: {
7621 LValue key = lowJSValue(m_node->child1(), ManualOperandSpeculation);
7622 speculate(m_node->child1());
7623 setInt32(wangsInt64Hash(key));
7624 return;
7625 }
7626
7627 case CellUse: {
7628 LBasicBlock isString = m_out.newBlock();
7629 LBasicBlock notString = m_out.newBlock();
7630 LBasicBlock continuation = m_out.newBlock();
7631
7632 LValue value = lowCell(m_node->child1());
7633 LValue isStringValue = m_out.equal(m_out.load8ZeroExt32(value, m_heaps.JSCell_typeInfoType), m_out.constInt32(StringType));
7634 m_out.branch(
7635 isStringValue, unsure(isString), unsure(notString));
7636
7637 LBasicBlock lastNext = m_out.appendTo(isString, notString);
7638 ValueFromBlock stringResult = m_out.anchor(mapHashString(value));
7639 m_out.jump(continuation);
7640
7641 m_out.appendTo(notString, continuation);
7642 ValueFromBlock notStringResult = m_out.anchor(wangsInt64Hash(value));
7643 m_out.jump(continuation);
7644
7645 m_out.appendTo(continuation, lastNext);
7646 setInt32(m_out.phi(Int32, stringResult, notStringResult));
7647 return;
7648 }
7649
7650 case StringUse: {
7651 LValue string = lowString(m_node->child1());
7652 setInt32(mapHashString(string));
7653 return;
7654 }
7655
7656 default:
7657 RELEASE_ASSERT(m_node->child1().useKind() == UntypedUse);
7658 break;
7659 }
7660
7661 LValue value = lowJSValue(m_node->child1());
7662
7663 LBasicBlock isCellCase = m_out.newBlock();
7664 LBasicBlock notCell = m_out.newBlock();
7665 LBasicBlock slowCase = m_out.newBlock();
7666 LBasicBlock straightHash = m_out.newBlock();
7667 LBasicBlock isNumberCase = m_out.newBlock();
7668 LBasicBlock isStringCase = m_out.newBlock();
7669 LBasicBlock nonEmptyStringCase = m_out.newBlock();
7670 LBasicBlock continuation = m_out.newBlock();
7671
7672 m_out.branch(
7673 isCell(value, provenType(m_node->child1())), unsure(isCellCase), unsure(notCell));
7674
7675 LBasicBlock lastNext = m_out.appendTo(isCellCase, isStringCase);
7676 LValue isString = m_out.equal(m_out.load8ZeroExt32(value, m_heaps.JSCell_typeInfoType), m_out.constInt32(StringType));
7677 m_out.branch(
7678 isString, unsure(isStringCase), unsure(straightHash));
7679
7680 m_out.appendTo(isStringCase, nonEmptyStringCase);
7681 LValue stringImpl = m_out.loadPtr(value, m_heaps.JSString_value);
7682 m_out.branch(
7683 m_out.equal(stringImpl, m_out.constIntPtr(0)), rarely(slowCase), usually(nonEmptyStringCase));
7684
7685 m_out.appendTo(nonEmptyStringCase, notCell);
7686 LValue hash = m_out.lShr(m_out.load32(stringImpl, m_heaps.StringImpl_hashAndFlags), m_out.constInt32(StringImpl::s_flagCount));
7687 ValueFromBlock nonEmptyStringHashResult = m_out.anchor(hash);
7688 m_out.branch(m_out.equal(hash, m_out.constInt32(0)),
7689 unsure(slowCase), unsure(continuation));
7690
7691 m_out.appendTo(notCell, isNumberCase);
7692 m_out.branch(
7693 isNumber(value), unsure(isNumberCase), unsure(straightHash));
7694
7695 m_out.appendTo(isNumberCase, straightHash);
7696 m_out.branch(
7697 isInt32(value), unsure(straightHash), unsure(slowCase));
7698
7699 m_out.appendTo(straightHash, slowCase);
7700 ValueFromBlock fastResult = m_out.anchor(wangsInt64Hash(value));
sbarati@apple.com21fc86e2016-09-06 23:22:01 +00007701 m_out.jump(continuation);
7702
7703 m_out.appendTo(slowCase, continuation);
7704 ValueFromBlock slowResult = m_out.anchor(
7705 vmCall(Int32, m_out.operation(operationMapHash), m_callFrame, value));
7706 m_out.jump(continuation);
7707
7708 m_out.appendTo(continuation, lastNext);
7709 setInt32(m_out.phi(Int32, fastResult, slowResult, nonEmptyStringHashResult));
7710 }
7711
7712 void compileGetMapBucket()
7713 {
7714 LBasicBlock loopStart = m_out.newBlock();
7715 LBasicBlock loopAround = m_out.newBlock();
7716 LBasicBlock slowPath = m_out.newBlock();
7717 LBasicBlock notPresentInTable = m_out.newBlock();
7718 LBasicBlock notEmptyValue = m_out.newBlock();
7719 LBasicBlock notDeletedValue = m_out.newBlock();
sbarati@apple.com21fc86e2016-09-06 23:22:01 +00007720 LBasicBlock continuation = m_out.newBlock();
7721
7722 LBasicBlock lastNext = m_out.insertNewBlocksBefore(loopStart);
7723
7724 LValue map;
7725 if (m_node->child1().useKind() == MapObjectUse)
7726 map = lowMapObject(m_node->child1());
7727 else if (m_node->child1().useKind() == SetObjectUse)
7728 map = lowSetObject(m_node->child1());
7729 else
7730 RELEASE_ASSERT_NOT_REACHED();
7731
sbarati@apple.com0868a692016-10-04 00:35:52 +00007732 LValue key = lowJSValue(m_node->child2(), ManualOperandSpeculation);
7733 if (m_node->child2().useKind() != UntypedUse)
7734 speculate(m_node->child2());
7735
sbarati@apple.com21fc86e2016-09-06 23:22:01 +00007736 LValue hash = lowInt32(m_node->child3());
7737
7738 LValue hashMapImpl = m_out.loadPtr(map, m_node->child1().useKind() == MapObjectUse ? m_heaps.JSMap_hashMapImpl : m_heaps.JSSet_hashMapImpl);
7739 LValue buffer = m_out.loadPtr(hashMapImpl, m_heaps.HashMapImpl_buffer);
7740 LValue mask = m_out.sub(m_out.load32(hashMapImpl, m_heaps.HashMapImpl_capacity), m_out.int32One);
7741
7742 ValueFromBlock indexStart = m_out.anchor(hash);
7743 m_out.jump(loopStart);
7744
7745 m_out.appendTo(loopStart, notEmptyValue);
7746 LValue unmaskedIndex = m_out.phi(Int32, indexStart);
7747 LValue index = m_out.bitAnd(mask, unmaskedIndex);
7748 LValue hashMapBucket = m_out.load64(m_out.baseIndex(m_heaps.properties.atAnyNumber(), buffer, m_out.zeroExt(index, Int64), ScaleEight));
7749 ValueFromBlock bucketResult = m_out.anchor(hashMapBucket);
sbarati@apple.com239d20b2017-01-26 23:50:58 +00007750 m_out.branch(m_out.equal(hashMapBucket, m_out.constIntPtr(bitwise_cast<intptr_t>(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::emptyValue()))),
sbarati@apple.com21fc86e2016-09-06 23:22:01 +00007751 unsure(notPresentInTable), unsure(notEmptyValue));
7752
7753 m_out.appendTo(notEmptyValue, notDeletedValue);
sbarati@apple.com239d20b2017-01-26 23:50:58 +00007754 m_out.branch(m_out.equal(hashMapBucket, m_out.constIntPtr(bitwise_cast<intptr_t>(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::deletedValue()))),
sbarati@apple.com21fc86e2016-09-06 23:22:01 +00007755 unsure(loopAround), unsure(notDeletedValue));
7756
sbarati@apple.com0868a692016-10-04 00:35:52 +00007757 m_out.appendTo(notDeletedValue, loopAround);
sbarati@apple.com21fc86e2016-09-06 23:22:01 +00007758 LValue bucketKey = m_out.load64(hashMapBucket, m_heaps.HashMapBucket_key);
sbarati@apple.com0868a692016-10-04 00:35:52 +00007759
sbarati@apple.com21fc86e2016-09-06 23:22:01 +00007760 // Perform Object.is()
sbarati@apple.com0868a692016-10-04 00:35:52 +00007761 switch (m_node->child2().useKind()) {
7762 case BooleanUse:
7763 case Int32Use:
7764 case SymbolUse:
7765 case ObjectUse: {
7766 m_out.branch(m_out.equal(key, bucketKey),
7767 unsure(continuation), unsure(loopAround));
7768 break;
7769 }
7770 case StringUse: {
7771 LBasicBlock notBitEqual = m_out.newBlock();
7772 LBasicBlock bucketKeyIsCell = m_out.newBlock();
sbarati@apple.com21fc86e2016-09-06 23:22:01 +00007773
sbarati@apple.com0868a692016-10-04 00:35:52 +00007774 m_out.branch(m_out.equal(key, bucketKey),
7775 unsure(continuation), unsure(notBitEqual));
sbarati@apple.com21fc86e2016-09-06 23:22:01 +00007776
sbarati@apple.com0868a692016-10-04 00:35:52 +00007777 m_out.appendTo(notBitEqual, bucketKeyIsCell);
7778 m_out.branch(isCell(bucketKey),
7779 unsure(bucketKeyIsCell), unsure(loopAround));
sbarati@apple.com21fc86e2016-09-06 23:22:01 +00007780
sbarati@apple.com0868a692016-10-04 00:35:52 +00007781 m_out.appendTo(bucketKeyIsCell, loopAround);
7782 m_out.branch(isString(bucketKey),
7783 unsure(slowPath), unsure(loopAround));
7784 break;
7785 }
7786 case CellUse: {
7787 LBasicBlock notBitEqual = m_out.newBlock();
7788 LBasicBlock bucketKeyIsCell = m_out.newBlock();
7789 LBasicBlock bucketKeyIsString = m_out.newBlock();
sbarati@apple.com21fc86e2016-09-06 23:22:01 +00007790
sbarati@apple.com0868a692016-10-04 00:35:52 +00007791 m_out.branch(m_out.equal(key, bucketKey),
7792 unsure(continuation), unsure(notBitEqual));
sbarati@apple.com21fc86e2016-09-06 23:22:01 +00007793
sbarati@apple.com0868a692016-10-04 00:35:52 +00007794 m_out.appendTo(notBitEqual, bucketKeyIsCell);
7795 m_out.branch(isCell(bucketKey),
7796 unsure(bucketKeyIsCell), unsure(loopAround));
sbarati@apple.com21fc86e2016-09-06 23:22:01 +00007797
sbarati@apple.com0868a692016-10-04 00:35:52 +00007798 m_out.appendTo(bucketKeyIsCell, bucketKeyIsString);
7799 m_out.branch(isString(bucketKey),
7800 unsure(bucketKeyIsString), unsure(loopAround));
sbarati@apple.com21fc86e2016-09-06 23:22:01 +00007801
sbarati@apple.com0868a692016-10-04 00:35:52 +00007802 m_out.appendTo(bucketKeyIsString, loopAround);
7803 m_out.branch(isString(key),
7804 unsure(slowPath), unsure(loopAround));
7805 break;
7806 }
7807 case UntypedUse: {
7808 LBasicBlock notBitEqual = m_out.newBlock();
7809 LBasicBlock bucketKeyIsCell = m_out.newBlock();
7810 LBasicBlock bothAreCells = m_out.newBlock();
7811 LBasicBlock bucketKeyIsString = m_out.newBlock();
7812 LBasicBlock bucketKeyNotCell = m_out.newBlock();
7813 LBasicBlock bucketKeyIsNumber = m_out.newBlock();
7814 LBasicBlock bothAreNumbers = m_out.newBlock();
7815 LBasicBlock bucketKeyIsInt32 = m_out.newBlock();
sbarati@apple.com21fc86e2016-09-06 23:22:01 +00007816
sbarati@apple.com0868a692016-10-04 00:35:52 +00007817 m_out.branch(m_out.equal(key, bucketKey),
7818 unsure(continuation), unsure(notBitEqual));
7819
7820 m_out.appendTo(notBitEqual, bucketKeyIsCell);
7821 m_out.branch(isCell(bucketKey),
7822 unsure(bucketKeyIsCell), unsure(bucketKeyNotCell));
7823
7824 m_out.appendTo(bucketKeyIsCell, bothAreCells);
7825 m_out.branch(isCell(key),
7826 unsure(bothAreCells), unsure(loopAround));
7827
7828 m_out.appendTo(bothAreCells, bucketKeyIsString);
7829 m_out.branch(isString(bucketKey),
7830 unsure(bucketKeyIsString), unsure(loopAround));
7831
7832 m_out.appendTo(bucketKeyIsString, bucketKeyNotCell);
7833 m_out.branch(isString(key),
7834 unsure(slowPath), unsure(loopAround));
7835
7836 m_out.appendTo(bucketKeyNotCell, bucketKeyIsNumber);
7837 m_out.branch(isNotNumber(bucketKey),
7838 unsure(loopAround), unsure(bucketKeyIsNumber));
7839
7840 m_out.appendTo(bucketKeyIsNumber, bothAreNumbers);
7841 m_out.branch(isNotNumber(key),
7842 unsure(loopAround), unsure(bothAreNumbers));
7843
7844 m_out.appendTo(bothAreNumbers, bucketKeyIsInt32);
7845 m_out.branch(isNotInt32(bucketKey),
7846 unsure(slowPath), unsure(bucketKeyIsInt32));
7847
7848 m_out.appendTo(bucketKeyIsInt32, loopAround);
7849 m_out.branch(isNotInt32(key),
7850 unsure(slowPath), unsure(loopAround));
7851 break;
7852 }
7853 default:
7854 RELEASE_ASSERT_NOT_REACHED();
7855 }
sbarati@apple.com21fc86e2016-09-06 23:22:01 +00007856
7857 m_out.appendTo(loopAround, slowPath);
7858 m_out.addIncomingToPhi(unmaskedIndex, m_out.anchor(m_out.add(index, m_out.int32One)));
7859 m_out.jump(loopStart);
7860
7861 m_out.appendTo(slowPath, notPresentInTable);
7862 ValueFromBlock slowPathResult = m_out.anchor(vmCall(pointerType(),
7863 m_out.operation(m_node->child1().useKind() == MapObjectUse ? operationJSMapFindBucket : operationJSSetFindBucket), m_callFrame, map, key, hash));
7864 m_out.jump(continuation);
7865
7866 m_out.appendTo(notPresentInTable, continuation);
7867 ValueFromBlock notPresentResult = m_out.anchor(m_out.constIntPtr(0));
7868 m_out.jump(continuation);
7869
7870 m_out.appendTo(continuation, lastNext);
7871 setMapBucket(m_out.phi(pointerType(), bucketResult, slowPathResult, notPresentResult));
7872 }
7873
7874 void compileLoadFromJSMapBucket()
7875 {
7876 LValue mapBucket = lowMapBucket(m_node->child1());
7877
7878 LBasicBlock continuation = m_out.newBlock();
7879 LBasicBlock hasBucket = m_out.newBlock();
7880
7881 ValueFromBlock noBucketResult = m_out.anchor(m_out.constInt64(JSValue::encode(jsUndefined())));
7882
7883 m_out.branch(m_out.equal(mapBucket, m_out.constIntPtr(0)),
7884 unsure(continuation), unsure(hasBucket));
7885
7886 LBasicBlock lastNext = m_out.appendTo(hasBucket, continuation);
7887 ValueFromBlock bucketResult = m_out.anchor(m_out.load64(mapBucket, m_heaps.HashMapBucket_value));
7888 m_out.jump(continuation);
7889
7890 m_out.appendTo(continuation, lastNext);
7891 setJSValue(m_out.phi(Int64, noBucketResult, bucketResult));
7892 }
7893
7894 void compileIsNonEmptyMapBucket()
7895 {
7896 LValue bucket = lowMapBucket(m_node->child1());
7897 LValue result = m_out.notEqual(bucket, m_out.constIntPtr(0));
7898 setBoolean(result);
7899 }
7900
utatane.tea@gmail.com0bfb74c2015-02-24 23:01:58 +00007901 void compileIsObjectOrNull()
7902 {
fpizlo@apple.comb8823d52015-05-03 00:15:27 +00007903 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
7904
7905 Edge child = m_node->child1();
7906 LValue value = lowJSValue(child);
7907
fpizlo@apple.com91331742016-03-07 02:07:28 +00007908 LBasicBlock cellCase = m_out.newBlock();
7909 LBasicBlock notFunctionCase = m_out.newBlock();
7910 LBasicBlock objectCase = m_out.newBlock();
7911 LBasicBlock slowPath = m_out.newBlock();
7912 LBasicBlock notCellCase = m_out.newBlock();
7913 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.comb8823d52015-05-03 00:15:27 +00007914
7915 m_out.branch(isCell(value, provenType(child)), unsure(cellCase), unsure(notCellCase));
7916
7917 LBasicBlock lastNext = m_out.appendTo(cellCase, notFunctionCase);
7918 ValueFromBlock isFunctionResult = m_out.anchor(m_out.booleanFalse);
7919 m_out.branch(
7920 isFunction(value, provenType(child)),
7921 unsure(continuation), unsure(notFunctionCase));
7922
7923 m_out.appendTo(notFunctionCase, objectCase);
7924 ValueFromBlock notObjectResult = m_out.anchor(m_out.booleanFalse);
7925 m_out.branch(
7926 isObject(value, provenType(child)),
7927 unsure(objectCase), unsure(continuation));
7928
7929 m_out.appendTo(objectCase, slowPath);
7930 ValueFromBlock objectResult = m_out.anchor(m_out.booleanTrue);
7931 m_out.branch(
7932 isExoticForTypeof(value, provenType(child)),
7933 rarely(slowPath), usually(continuation));
7934
7935 m_out.appendTo(slowPath, notCellCase);
fpizlo@apple.com6e697962015-10-12 17:56:26 +00007936 LValue slowResultValue = lazySlowPath(
7937 [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
7938 return createLazyCallGenerator(
7939 operationObjectIsObject, locations[0].directGPR(),
7940 CCallHelpers::TrustedImmPtr(globalObject), locations[1].directGPR());
7941 }, value);
7942 ValueFromBlock slowResult = m_out.anchor(m_out.notZero64(slowResultValue));
fpizlo@apple.comb8823d52015-05-03 00:15:27 +00007943 m_out.jump(continuation);
7944
7945 m_out.appendTo(notCellCase, continuation);
7946 LValue notCellResultValue = m_out.equal(value, m_out.constInt64(JSValue::encode(jsNull())));
7947 ValueFromBlock notCellResult = m_out.anchor(notCellResultValue);
7948 m_out.jump(continuation);
7949
7950 m_out.appendTo(continuation, lastNext);
7951 LValue result = m_out.phi(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00007952 Int32,
fpizlo@apple.comb8823d52015-05-03 00:15:27 +00007953 isFunctionResult, notObjectResult, objectResult, slowResult, notCellResult);
7954 setBoolean(result);
fpizlo@apple.com40750682014-03-13 22:18:50 +00007955 }
7956
7957 void compileIsFunction()
7958 {
fpizlo@apple.comb8823d52015-05-03 00:15:27 +00007959 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
7960
7961 Edge child = m_node->child1();
7962 LValue value = lowJSValue(child);
7963
fpizlo@apple.com91331742016-03-07 02:07:28 +00007964 LBasicBlock cellCase = m_out.newBlock();
7965 LBasicBlock notFunctionCase = m_out.newBlock();
7966 LBasicBlock slowPath = m_out.newBlock();
7967 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.comb8823d52015-05-03 00:15:27 +00007968
7969 ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse);
7970 m_out.branch(
7971 isCell(value, provenType(child)), unsure(cellCase), unsure(continuation));
7972
7973 LBasicBlock lastNext = m_out.appendTo(cellCase, notFunctionCase);
7974 ValueFromBlock functionResult = m_out.anchor(m_out.booleanTrue);
7975 m_out.branch(
7976 isFunction(value, provenType(child)),
7977 unsure(continuation), unsure(notFunctionCase));
7978
7979 m_out.appendTo(notFunctionCase, slowPath);
7980 ValueFromBlock objectResult = m_out.anchor(m_out.booleanFalse);
7981 m_out.branch(
7982 isExoticForTypeof(value, provenType(child)),
7983 rarely(slowPath), usually(continuation));
7984
7985 m_out.appendTo(slowPath, continuation);
fpizlo@apple.com6e697962015-10-12 17:56:26 +00007986 LValue slowResultValue = lazySlowPath(
7987 [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
7988 return createLazyCallGenerator(
7989 operationObjectIsFunction, locations[0].directGPR(),
7990 CCallHelpers::TrustedImmPtr(globalObject), locations[1].directGPR());
7991 }, value);
fpizlo@apple.comb8823d52015-05-03 00:15:27 +00007992 ValueFromBlock slowResult = m_out.anchor(m_out.notNull(slowResultValue));
7993 m_out.jump(continuation);
7994
7995 m_out.appendTo(continuation, lastNext);
7996 LValue result = m_out.phi(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00007997 Int32, notCellResult, functionResult, objectResult, slowResult);
fpizlo@apple.comb8823d52015-05-03 00:15:27 +00007998 setBoolean(result);
7999 }
mark.lam@apple.com2c87b1a2016-04-20 00:02:07 +00008000
keith_miller@apple.com6919bc12016-06-23 01:39:01 +00008001 void compileIsTypedArrayView()
8002 {
8003 LValue value = lowJSValue(m_node->child1());
8004
8005 LBasicBlock isCellCase = m_out.newBlock();
8006 LBasicBlock continuation = m_out.newBlock();
8007
8008 ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse);
8009 m_out.branch(isCell(value, provenType(m_node->child1())), unsure(isCellCase), unsure(continuation));
8010
8011 LBasicBlock lastNext = m_out.appendTo(isCellCase, continuation);
8012 ValueFromBlock cellResult = m_out.anchor(isTypedArrayView(value, provenType(m_node->child1())));
8013 m_out.jump(continuation);
8014
8015 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008016 setBoolean(m_out.phi(Int32, notCellResult, cellResult));
keith_miller@apple.com6919bc12016-06-23 01:39:01 +00008017 }
8018
fpizlo@apple.comb8823d52015-05-03 00:15:27 +00008019 void compileTypeOf()
8020 {
8021 Edge child = m_node->child1();
8022 LValue value = lowJSValue(child);
8023
fpizlo@apple.com91331742016-03-07 02:07:28 +00008024 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.comb8823d52015-05-03 00:15:27 +00008025 LBasicBlock lastNext = m_out.insertNewBlocksBefore(continuation);
8026
8027 Vector<ValueFromBlock> results;
8028
8029 buildTypeOf(
8030 child, value,
8031 [&] (TypeofType type) {
8032 results.append(m_out.anchor(weakPointer(vm().smallStrings.typeString(type))));
8033 m_out.jump(continuation);
8034 });
8035
8036 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008037 setJSValue(m_out.phi(Int64, results));
fpizlo@apple.com40750682014-03-13 22:18:50 +00008038 }
8039
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00008040 void compileIn()
8041 {
commit-queue@webkit.org5d428a22016-09-02 23:13:50 +00008042 DFG_ASSERT(m_graph, m_node, m_node->child2().useKind() == CellUse);
8043
fpizlo@apple.com475458a2016-01-05 20:39:27 +00008044 Node* node = m_node;
8045 Edge base = node->child2();
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00008046 LValue cell = lowCell(base);
fpizlo@apple.com475458a2016-01-05 20:39:27 +00008047 if (JSString* string = node->child1()->dynamicCastConstant<JSString*>()) {
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00008048 if (string->tryGetValueImpl() && string->tryGetValueImpl()->isAtomic()) {
fpizlo@apple.com6e697962015-10-12 17:56:26 +00008049 UniquedStringImpl* str = bitwise_cast<UniquedStringImpl*>(string->tryGetValueImpl());
fpizlo@apple.com475458a2016-01-05 20:39:27 +00008050 B3::PatchpointValue* patchpoint = m_out.patchpoint(Int64);
fpizlo@apple.com45e45652016-01-07 21:20:37 +00008051 patchpoint->appendSomeRegister(cell);
sbarati@apple.com15af88b2016-05-11 20:54:09 +00008052 patchpoint->append(m_tagMask, ValueRep::lateReg(GPRInfo::tagMaskRegister));
8053 patchpoint->append(m_tagTypeNumber, ValueRep::lateReg(GPRInfo::tagTypeNumberRegister));
fpizlo@apple.com475458a2016-01-05 20:39:27 +00008054 patchpoint->clobber(RegisterSet::macroScratchRegisters());
8055
keith_miller@apple.coma64964a2016-04-22 02:28:00 +00008056 RefPtr<PatchpointExceptionHandle> exceptionHandle = preparePatchpointForExceptions(patchpoint);
8057
fpizlo@apple.com475458a2016-01-05 20:39:27 +00008058 State* state = &m_ftlState;
8059 patchpoint->setGenerator(
8060 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
8061 AllowMacroScratchRegisterUsage allowScratch(jit);
8062
keith_miller@apple.coma64964a2016-04-22 02:28:00 +00008063 // This is the direct exit target for operation calls. We don't need a JS exceptionHandle because we don't
8064 // cache Proxy objects.
8065 Box<CCallHelpers::JumpList> exceptions = exceptionHandle->scheduleExitCreation(params)->jumps(jit);
8066
fpizlo@apple.com475458a2016-01-05 20:39:27 +00008067 GPRReg baseGPR = params[1].gpr();
8068 GPRReg resultGPR = params[0].gpr();
8069
8070 StructureStubInfo* stubInfo =
8071 jit.codeBlock()->addStubInfo(AccessType::In);
8072 stubInfo->callSiteIndex =
8073 state->jitCode->common.addCodeOrigin(node->origin.semantic);
8074 stubInfo->codeOrigin = node->origin.semantic;
8075 stubInfo->patch.baseGPR = static_cast<int8_t>(baseGPR);
8076 stubInfo->patch.valueGPR = static_cast<int8_t>(resultGPR);
8077 stubInfo->patch.usedRegisters = params.unavailableRegisters();
8078
8079 CCallHelpers::PatchableJump jump = jit.patchableJump();
8080 CCallHelpers::Label done = jit.label();
8081
8082 params.addLatePath(
8083 [=] (CCallHelpers& jit) {
8084 AllowMacroScratchRegisterUsage allowScratch(jit);
8085
8086 jump.m_jump.link(&jit);
8087 CCallHelpers::Label slowPathBegin = jit.label();
8088 CCallHelpers::Call slowPathCall = callOperation(
8089 *state, params.unavailableRegisters(), jit,
keith_miller@apple.coma64964a2016-04-22 02:28:00 +00008090 node->origin.semantic, exceptions.get(), operationInOptimize,
fpizlo@apple.com475458a2016-01-05 20:39:27 +00008091 resultGPR, CCallHelpers::TrustedImmPtr(stubInfo), baseGPR,
8092 CCallHelpers::TrustedImmPtr(str)).call();
8093 jit.jump().linkTo(done, &jit);
8094
8095 jit.addLinkTask(
8096 [=] (LinkBuffer& linkBuffer) {
sbarati@apple.comb5bee812016-06-19 19:42:18 +00008097 CodeLocationLabel start = linkBuffer.locationOf(jump);
8098 stubInfo->patch.start = start;
8099 ptrdiff_t inlineSize = MacroAssembler::differenceBetweenCodePtr(
8100 start, linkBuffer.locationOf(done));
8101 RELEASE_ASSERT(inlineSize >= 0);
8102 stubInfo->patch.inlineSize = inlineSize;
8103
8104 stubInfo->patch.deltaFromStartToSlowPathCallLocation = MacroAssembler::differenceBetweenCodePtr(
8105 start, linkBuffer.locationOf(slowPathCall));
8106
8107 stubInfo->patch.deltaFromStartToSlowPathStart = MacroAssembler::differenceBetweenCodePtr(
8108 start, linkBuffer.locationOf(slowPathBegin));
8109
fpizlo@apple.com475458a2016-01-05 20:39:27 +00008110 });
8111 });
8112 });
8113
8114 setJSValue(patchpoint);
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00008115 return;
8116 }
8117 }
8118
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008119 setJSValue(vmCall(Int64, m_out.operation(operationGenericIn), m_callFrame, cell, lowJSValue(m_node->child1())));
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00008120 }
8121
sbarati@apple.coma3db4652016-09-20 01:05:50 +00008122 void compileHasOwnProperty()
8123 {
8124 LBasicBlock slowCase = m_out.newBlock();
8125 LBasicBlock continuation = m_out.newBlock();
8126 LBasicBlock lastNext = nullptr;
8127
8128 LValue object = lowObject(m_node->child1());
8129 LValue uniquedStringImpl;
8130 LValue keyAsValue = nullptr;
8131 switch (m_node->child2().useKind()) {
8132 case StringUse: {
8133 LBasicBlock isNonEmptyString = m_out.newBlock();
8134 LBasicBlock isAtomicString = m_out.newBlock();
8135
8136 keyAsValue = lowString(m_node->child2());
8137 uniquedStringImpl = m_out.loadPtr(keyAsValue, m_heaps.JSString_value);
8138 m_out.branch(m_out.notNull(uniquedStringImpl), usually(isNonEmptyString), rarely(slowCase));
8139
8140 lastNext = m_out.appendTo(isNonEmptyString, isAtomicString);
8141 LValue isNotAtomic = m_out.testIsZero32(m_out.load32(uniquedStringImpl, m_heaps.StringImpl_hashAndFlags), m_out.constInt32(StringImpl::flagIsAtomic()));
8142 m_out.branch(isNotAtomic, rarely(slowCase), usually(isAtomicString));
8143
8144 m_out.appendTo(isAtomicString, slowCase);
8145 break;
8146 }
8147 case SymbolUse: {
8148 keyAsValue = lowSymbol(m_node->child2());
8149 uniquedStringImpl = m_out.loadPtr(keyAsValue, m_heaps.Symbol_symbolImpl);
8150 lastNext = m_out.insertNewBlocksBefore(slowCase);
8151 break;
8152 }
8153 case UntypedUse: {
8154 LBasicBlock isCellCase = m_out.newBlock();
8155 LBasicBlock isStringCase = m_out.newBlock();
8156 LBasicBlock notStringCase = m_out.newBlock();
8157 LBasicBlock isNonEmptyString = m_out.newBlock();
8158 LBasicBlock isSymbolCase = m_out.newBlock();
8159 LBasicBlock hasUniquedStringImpl = m_out.newBlock();
8160
8161 keyAsValue = lowJSValue(m_node->child2());
8162 m_out.branch(isCell(keyAsValue), usually(isCellCase), rarely(slowCase));
8163
8164 lastNext = m_out.appendTo(isCellCase, isStringCase);
8165 m_out.branch(isString(keyAsValue), unsure(isStringCase), unsure(notStringCase));
8166
8167 m_out.appendTo(isStringCase, isNonEmptyString);
8168 LValue implFromString = m_out.loadPtr(keyAsValue, m_heaps.JSString_value);
8169 ValueFromBlock stringResult = m_out.anchor(implFromString);
8170 m_out.branch(m_out.notNull(implFromString), usually(isNonEmptyString), rarely(slowCase));
8171
8172 m_out.appendTo(isNonEmptyString, notStringCase);
8173 LValue isNotAtomic = m_out.testIsZero32(m_out.load32(implFromString, m_heaps.StringImpl_hashAndFlags), m_out.constInt32(StringImpl::flagIsAtomic()));
8174 m_out.branch(isNotAtomic, rarely(slowCase), usually(hasUniquedStringImpl));
8175
8176 m_out.appendTo(notStringCase, isSymbolCase);
8177 m_out.branch(isSymbol(keyAsValue), unsure(isSymbolCase), unsure(slowCase));
8178
8179 m_out.appendTo(isSymbolCase, hasUniquedStringImpl);
8180 ValueFromBlock symbolResult = m_out.anchor(m_out.loadPtr(keyAsValue, m_heaps.Symbol_symbolImpl));
8181 m_out.jump(hasUniquedStringImpl);
8182
8183 m_out.appendTo(hasUniquedStringImpl, slowCase);
8184 uniquedStringImpl = m_out.phi(pointerType(), stringResult, symbolResult);
8185 break;
8186 }
8187 default:
8188 RELEASE_ASSERT_NOT_REACHED();
8189 }
8190
8191 ASSERT(keyAsValue);
8192
8193 // Note that we don't test if the hash is zero here. AtomicStringImpl's can't have a zero
8194 // hash, however, a SymbolImpl may. But, because this is a cache, we don't care. We only
8195 // ever load the result from the cache if the cache entry matches what we are querying for.
8196 // So we either get super lucky and use zero for the hash and somehow collide with the entity
8197 // we're looking for, or we realize we're comparing against another entity, and go to the
8198 // slow path anyways.
8199 LValue hash = m_out.lShr(m_out.load32(uniquedStringImpl, m_heaps.StringImpl_hashAndFlags), m_out.constInt32(StringImpl::s_flagCount));
8200
8201 LValue structureID = m_out.load32(object, m_heaps.JSCell_structureID);
8202 LValue index = m_out.add(hash, structureID);
8203 index = m_out.zeroExtPtr(m_out.bitAnd(index, m_out.constInt32(HasOwnPropertyCache::mask)));
8204 ASSERT(vm().hasOwnPropertyCache());
8205 LValue cache = m_out.constIntPtr(vm().hasOwnPropertyCache());
8206
8207 IndexedAbstractHeap& heap = m_heaps.HasOwnPropertyCache;
8208 LValue sameStructureID = m_out.equal(structureID, m_out.load32(m_out.baseIndex(heap, cache, index, JSValue(), HasOwnPropertyCache::Entry::offsetOfStructureID())));
8209 LValue sameImpl = m_out.equal(uniquedStringImpl, m_out.loadPtr(m_out.baseIndex(heap, cache, index, JSValue(), HasOwnPropertyCache::Entry::offsetOfImpl())));
8210 ValueFromBlock fastResult = m_out.anchor(m_out.load8ZeroExt32(m_out.baseIndex(heap, cache, index, JSValue(), HasOwnPropertyCache::Entry::offsetOfResult())));
8211 LValue cacheHit = m_out.bitAnd(sameStructureID, sameImpl);
8212
8213 m_out.branch(m_out.notZero32(cacheHit), usually(continuation), rarely(slowCase));
8214
8215 m_out.appendTo(slowCase, continuation);
8216 ValueFromBlock slowResult;
8217 slowResult = m_out.anchor(vmCall(Int32, m_out.operation(operationHasOwnProperty), m_callFrame, object, keyAsValue));
8218 m_out.jump(continuation);
8219
8220 m_out.appendTo(continuation, lastNext);
8221 setBoolean(m_out.phi(Int32, fastResult, slowResult));
8222 }
8223
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00008224 void compileOverridesHasInstance()
8225 {
sbarati@apple.com239d20b2017-01-26 23:50:58 +00008226 FrozenValue* defaultHasInstanceFunction = m_node->cellOperand();
8227 ASSERT(defaultHasInstanceFunction->cell()->inherits(JSFunction::info()));
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00008228
8229 LValue constructor = lowCell(m_node->child1());
8230 LValue hasInstance = lowJSValue(m_node->child2());
8231
fpizlo@apple.com91331742016-03-07 02:07:28 +00008232 LBasicBlock defaultHasInstance = m_out.newBlock();
8233 LBasicBlock continuation = m_out.newBlock();
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00008234
fpizlo@apple.com3ce6ab62016-02-18 16:40:25 +00008235 // Unlike in the DFG, we don't worry about cleaning this code up for the case where we have proven the hasInstanceValue is a constant as B3 should fix it for us.
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00008236
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00008237 ValueFromBlock notDefaultHasInstanceResult = m_out.anchor(m_out.booleanTrue);
sbarati@apple.com239d20b2017-01-26 23:50:58 +00008238 m_out.branch(m_out.notEqual(hasInstance, frozenPointer(defaultHasInstanceFunction)), unsure(continuation), unsure(defaultHasInstance));
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00008239
8240 LBasicBlock lastNext = m_out.appendTo(defaultHasInstance, continuation);
8241 ValueFromBlock implementsDefaultHasInstanceResult = m_out.anchor(m_out.testIsZero32(
8242 m_out.load8ZeroExt32(constructor, m_heaps.JSCell_typeInfoFlags),
8243 m_out.constInt32(ImplementsDefaultHasInstance)));
8244 m_out.jump(continuation);
8245
8246 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008247 setBoolean(m_out.phi(Int32, implementsDefaultHasInstanceResult, notDefaultHasInstanceResult));
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00008248 }
8249
8250 void compileCheckTypeInfoFlags()
fpizlo@apple.com44239d42014-03-16 06:02:43 +00008251 {
8252 speculate(
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00008253 BadTypeInfoFlags, noValue(), 0,
benjamin@webkit.org2e864d22015-11-17 06:20:21 +00008254 m_out.testIsZero32(
8255 m_out.load8ZeroExt32(lowCell(m_node->child1()), m_heaps.JSCell_typeInfoFlags),
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00008256 m_out.constInt32(m_node->typeInfoOperand())));
fpizlo@apple.com44239d42014-03-16 06:02:43 +00008257 }
8258
8259 void compileInstanceOf()
8260 {
8261 LValue cell;
8262
8263 if (m_node->child1().useKind() == UntypedUse)
8264 cell = lowJSValue(m_node->child1());
8265 else
8266 cell = lowCell(m_node->child1());
8267
8268 LValue prototype = lowCell(m_node->child2());
8269
fpizlo@apple.com91331742016-03-07 02:07:28 +00008270 LBasicBlock isCellCase = m_out.newBlock();
8271 LBasicBlock loop = m_out.newBlock();
8272 LBasicBlock notYetInstance = m_out.newBlock();
8273 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com1e36f7d2016-03-07 02:22:08 +00008274 LBasicBlock loadPrototypeDirect = m_out.newBlock();
8275 LBasicBlock defaultHasInstanceSlow = m_out.newBlock();
fpizlo@apple.com44239d42014-03-16 06:02:43 +00008276
8277 LValue condition;
8278 if (m_node->child1().useKind() == UntypedUse)
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00008279 condition = isCell(cell, provenType(m_node->child1()));
fpizlo@apple.com44239d42014-03-16 06:02:43 +00008280 else
8281 condition = m_out.booleanTrue;
8282
8283 ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse);
8284 m_out.branch(condition, unsure(isCellCase), unsure(continuation));
8285
8286 LBasicBlock lastNext = m_out.appendTo(isCellCase, loop);
8287
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00008288 speculate(BadType, noValue(), 0, isNotObject(prototype, provenType(m_node->child2())));
fpizlo@apple.com44239d42014-03-16 06:02:43 +00008289
8290 ValueFromBlock originalValue = m_out.anchor(cell);
8291 m_out.jump(loop);
8292
sbarati@apple.comfa857522016-03-07 01:00:33 +00008293 m_out.appendTo(loop, loadPrototypeDirect);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008294 LValue value = m_out.phi(Int64, originalValue);
sbarati@apple.comfa857522016-03-07 01:00:33 +00008295 LValue type = m_out.load8ZeroExt32(value, m_heaps.JSCell_typeInfoType);
8296 m_out.branch(
8297 m_out.notEqual(type, m_out.constInt32(ProxyObjectType)),
8298 usually(loadPrototypeDirect), rarely(defaultHasInstanceSlow));
8299
8300 m_out.appendTo(loadPrototypeDirect, notYetInstance);
fpizlo@apple.com44239d42014-03-16 06:02:43 +00008301 LValue structure = loadStructure(value);
8302 LValue currentPrototype = m_out.load64(structure, m_heaps.Structure_prototype);
8303 ValueFromBlock isInstanceResult = m_out.anchor(m_out.booleanTrue);
8304 m_out.branch(
8305 m_out.equal(currentPrototype, prototype),
8306 unsure(continuation), unsure(notYetInstance));
8307
sbarati@apple.comfa857522016-03-07 01:00:33 +00008308 m_out.appendTo(notYetInstance, defaultHasInstanceSlow);
fpizlo@apple.com44239d42014-03-16 06:02:43 +00008309 ValueFromBlock notInstanceResult = m_out.anchor(m_out.booleanFalse);
benjamin@webkit.org81ec96c2015-11-18 23:14:54 +00008310 m_out.addIncomingToPhi(value, m_out.anchor(currentPrototype));
fpizlo@apple.com44239d42014-03-16 06:02:43 +00008311 m_out.branch(isCell(currentPrototype), unsure(loop), unsure(continuation));
sbarati@apple.comfa857522016-03-07 01:00:33 +00008312
8313 m_out.appendTo(defaultHasInstanceSlow, continuation);
8314 // We can use the value that we're looping with because we
8315 // can just continue off from wherever we bailed from the
8316 // loop.
8317 ValueFromBlock defaultHasInstanceResult = m_out.anchor(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008318 vmCall(Int32, m_out.operation(operationDefaultHasInstance), m_callFrame, value, prototype));
sbarati@apple.comfa857522016-03-07 01:00:33 +00008319 m_out.jump(continuation);
fpizlo@apple.com44239d42014-03-16 06:02:43 +00008320
8321 m_out.appendTo(continuation, lastNext);
8322 setBoolean(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008323 m_out.phi(Int32, notCellResult, isInstanceResult, notInstanceResult, defaultHasInstanceResult));
fpizlo@apple.com44239d42014-03-16 06:02:43 +00008324 }
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00008325
8326 void compileInstanceOfCustom()
8327 {
8328 LValue value = lowJSValue(m_node->child1());
8329 LValue constructor = lowCell(m_node->child2());
8330 LValue hasInstance = lowJSValue(m_node->child3());
8331
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008332 setBoolean(m_out.logicalNot(m_out.equal(m_out.constInt32(0), vmCall(Int32, m_out.operation(operationInstanceOfCustom), m_callFrame, value, constructor, hasInstance))));
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00008333 }
fpizlo@apple.com44239d42014-03-16 06:02:43 +00008334
msaboff@apple.com95894332014-01-29 19:18:54 +00008335 void compileCountExecution()
8336 {
8337 TypedPointer counter = m_out.absolute(m_node->executionCounter()->address());
8338 m_out.store64(m_out.add(m_out.load64(counter), m_out.constInt64(1)), counter);
8339 }
8340
fpizlo@apple.com40750682014-03-13 22:18:50 +00008341 void compileStoreBarrier()
8342 {
fpizlo@apple.com9a175952016-09-28 21:55:53 +00008343 emitStoreBarrier(lowCell(m_node->child1()), m_node->op() == FencedStoreBarrier);
fpizlo@apple.com40750682014-03-13 22:18:50 +00008344 }
fpizlo@apple.com9a175952016-09-28 21:55:53 +00008345
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008346 void compileHasIndexedProperty()
8347 {
8348 switch (m_node->arrayMode().type()) {
8349 case Array::Int32:
8350 case Array::Contiguous: {
8351 LValue base = lowCell(m_node->child1());
8352 LValue index = lowInt32(m_node->child2());
8353 LValue storage = lowStorage(m_node->child3());
8354
8355 IndexedAbstractHeap& heap = m_node->arrayMode().type() == Array::Int32 ?
8356 m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties;
8357
fpizlo@apple.com91331742016-03-07 02:07:28 +00008358 LBasicBlock checkHole = m_out.newBlock();
8359 LBasicBlock slowCase = m_out.newBlock();
8360 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008361
8362 if (!m_node->arrayMode().isInBounds()) {
8363 m_out.branch(
8364 m_out.aboveOrEqual(
8365 index, m_out.load32NonNegative(storage, m_heaps.Butterfly_publicLength)),
8366 rarely(slowCase), usually(checkHole));
8367 } else
8368 m_out.jump(checkHole);
8369
fpizlo@apple.com373ed6b2015-12-15 04:52:55 +00008370 LBasicBlock lastNext = m_out.appendTo(checkHole, slowCase);
8371 LValue checkHoleResultValue =
8372 m_out.notZero64(m_out.load64(baseIndex(heap, storage, index, m_node->child2())));
8373 ValueFromBlock checkHoleResult = m_out.anchor(checkHoleResultValue);
8374 m_out.branch(checkHoleResultValue, usually(continuation), rarely(slowCase));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008375
8376 m_out.appendTo(slowCase, continuation);
8377 ValueFromBlock slowResult = m_out.anchor(m_out.equal(
8378 m_out.constInt64(JSValue::encode(jsBoolean(true))),
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008379 vmCall(Int64, m_out.operation(operationHasIndexedProperty), m_callFrame, base, index)));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008380 m_out.jump(continuation);
8381
8382 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008383 setBoolean(m_out.phi(Int32, checkHoleResult, slowResult));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008384 return;
8385 }
8386 case Array::Double: {
8387 LValue base = lowCell(m_node->child1());
8388 LValue index = lowInt32(m_node->child2());
8389 LValue storage = lowStorage(m_node->child3());
8390
8391 IndexedAbstractHeap& heap = m_heaps.indexedDoubleProperties;
8392
fpizlo@apple.com91331742016-03-07 02:07:28 +00008393 LBasicBlock checkHole = m_out.newBlock();
8394 LBasicBlock slowCase = m_out.newBlock();
8395 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008396
8397 if (!m_node->arrayMode().isInBounds()) {
8398 m_out.branch(
8399 m_out.aboveOrEqual(
8400 index, m_out.load32NonNegative(storage, m_heaps.Butterfly_publicLength)),
8401 rarely(slowCase), usually(checkHole));
8402 } else
8403 m_out.jump(checkHole);
8404
8405 LBasicBlock lastNext = m_out.appendTo(checkHole, slowCase);
8406 LValue doubleValue = m_out.loadDouble(baseIndex(heap, storage, index, m_node->child2()));
fpizlo@apple.com373ed6b2015-12-15 04:52:55 +00008407 LValue checkHoleResultValue = m_out.doubleEqual(doubleValue, doubleValue);
8408 ValueFromBlock checkHoleResult = m_out.anchor(checkHoleResultValue);
8409 m_out.branch(checkHoleResultValue, usually(continuation), rarely(slowCase));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008410
8411 m_out.appendTo(slowCase, continuation);
8412 ValueFromBlock slowResult = m_out.anchor(m_out.equal(
8413 m_out.constInt64(JSValue::encode(jsBoolean(true))),
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008414 vmCall(Int64, m_out.operation(operationHasIndexedProperty), m_callFrame, base, index)));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008415 m_out.jump(continuation);
8416
8417 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008418 setBoolean(m_out.phi(Int32, checkHoleResult, slowResult));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008419 return;
8420 }
8421
8422 default:
8423 RELEASE_ASSERT_NOT_REACHED();
8424 return;
8425 }
8426 }
8427
8428 void compileHasGenericProperty()
8429 {
8430 LValue base = lowJSValue(m_node->child1());
8431 LValue property = lowCell(m_node->child2());
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008432 setJSValue(vmCall(Int64, m_out.operation(operationHasGenericProperty), m_callFrame, base, property));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008433 }
8434
8435 void compileHasStructureProperty()
8436 {
8437 LValue base = lowJSValue(m_node->child1());
8438 LValue property = lowString(m_node->child2());
8439 LValue enumerator = lowCell(m_node->child3());
8440
fpizlo@apple.com91331742016-03-07 02:07:28 +00008441 LBasicBlock correctStructure = m_out.newBlock();
8442 LBasicBlock wrongStructure = m_out.newBlock();
8443 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008444
8445 m_out.branch(m_out.notEqual(
8446 m_out.load32(base, m_heaps.JSCell_structureID),
8447 m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedStructureID)),
8448 rarely(wrongStructure), usually(correctStructure));
8449
8450 LBasicBlock lastNext = m_out.appendTo(correctStructure, wrongStructure);
8451 ValueFromBlock correctStructureResult = m_out.anchor(m_out.booleanTrue);
8452 m_out.jump(continuation);
8453
8454 m_out.appendTo(wrongStructure, continuation);
8455 ValueFromBlock wrongStructureResult = m_out.anchor(
8456 m_out.equal(
8457 m_out.constInt64(JSValue::encode(jsBoolean(true))),
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008458 vmCall(Int64, m_out.operation(operationHasGenericProperty), m_callFrame, base, property)));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008459 m_out.jump(continuation);
8460
8461 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008462 setBoolean(m_out.phi(Int32, correctStructureResult, wrongStructureResult));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008463 }
8464
8465 void compileGetDirectPname()
8466 {
8467 LValue base = lowCell(m_graph.varArgChild(m_node, 0));
8468 LValue property = lowCell(m_graph.varArgChild(m_node, 1));
8469 LValue index = lowInt32(m_graph.varArgChild(m_node, 2));
8470 LValue enumerator = lowCell(m_graph.varArgChild(m_node, 3));
8471
fpizlo@apple.com91331742016-03-07 02:07:28 +00008472 LBasicBlock checkOffset = m_out.newBlock();
8473 LBasicBlock inlineLoad = m_out.newBlock();
8474 LBasicBlock outOfLineLoad = m_out.newBlock();
8475 LBasicBlock slowCase = m_out.newBlock();
8476 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008477
8478 m_out.branch(m_out.notEqual(
8479 m_out.load32(base, m_heaps.JSCell_structureID),
8480 m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedStructureID)),
8481 rarely(slowCase), usually(checkOffset));
8482
8483 LBasicBlock lastNext = m_out.appendTo(checkOffset, inlineLoad);
8484 m_out.branch(m_out.aboveOrEqual(index, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedInlineCapacity)),
8485 unsure(outOfLineLoad), unsure(inlineLoad));
8486
8487 m_out.appendTo(inlineLoad, outOfLineLoad);
8488 ValueFromBlock inlineResult = m_out.anchor(
8489 m_out.load64(m_out.baseIndex(m_heaps.properties.atAnyNumber(),
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008490 base, m_out.zeroExt(index, Int64), ScaleEight, JSObject::offsetOfInlineStorage())));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008491 m_out.jump(continuation);
8492
8493 m_out.appendTo(outOfLineLoad, slowCase);
fpizlo@apple.com95ef6492016-03-15 15:26:36 +00008494 LValue storage = m_out.loadPtr(base, m_heaps.JSObject_butterfly);
commit-queue@webkit.org65fa3e42015-12-04 20:27:37 +00008495 LValue realIndex = m_out.signExt32To64(
8496 m_out.neg(m_out.sub(index, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedInlineCapacity))));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008497 int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);
8498 ValueFromBlock outOfLineResult = m_out.anchor(
8499 m_out.load64(m_out.baseIndex(m_heaps.properties.atAnyNumber(), storage, realIndex, ScaleEight, offsetOfFirstProperty)));
8500 m_out.jump(continuation);
8501
8502 m_out.appendTo(slowCase, continuation);
8503 ValueFromBlock slowCaseResult = m_out.anchor(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008504 vmCall(Int64, m_out.operation(operationGetByVal), m_callFrame, base, property));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008505 m_out.jump(continuation);
8506
8507 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008508 setJSValue(m_out.phi(Int64, inlineResult, outOfLineResult, slowCaseResult));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008509 }
8510
8511 void compileGetEnumerableLength()
8512 {
msaboff@apple.comb644c252015-03-24 10:05:21 +00008513 LValue enumerator = lowCell(m_node->child1());
8514 setInt32(m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_indexLength));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008515 }
8516
msaboff@apple.comb644c252015-03-24 10:05:21 +00008517 void compileGetPropertyEnumerator()
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008518 {
8519 LValue base = lowCell(m_node->child1());
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008520 setJSValue(vmCall(Int64, m_out.operation(operationGetPropertyEnumerator), m_callFrame, base));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008521 }
8522
msaboff@apple.comb644c252015-03-24 10:05:21 +00008523 void compileGetEnumeratorStructurePname()
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008524 {
8525 LValue enumerator = lowCell(m_node->child1());
8526 LValue index = lowInt32(m_node->child2());
8527
fpizlo@apple.com91331742016-03-07 02:07:28 +00008528 LBasicBlock inBounds = m_out.newBlock();
8529 LBasicBlock outOfBounds = m_out.newBlock();
8530 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008531
msaboff@apple.comb644c252015-03-24 10:05:21 +00008532 m_out.branch(m_out.below(index, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_endStructurePropertyIndex)),
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008533 usually(inBounds), rarely(outOfBounds));
8534
8535 LBasicBlock lastNext = m_out.appendTo(inBounds, outOfBounds);
8536 LValue storage = m_out.loadPtr(enumerator, m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector);
8537 ValueFromBlock inBoundsResult = m_out.anchor(
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00008538 m_out.loadPtr(m_out.baseIndex(m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVectorContents, storage, m_out.zeroExtPtr(index))));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008539 m_out.jump(continuation);
8540
8541 m_out.appendTo(outOfBounds, continuation);
8542 ValueFromBlock outOfBoundsResult = m_out.anchor(m_out.constInt64(ValueNull));
8543 m_out.jump(continuation);
8544
8545 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008546 setJSValue(m_out.phi(Int64, inBoundsResult, outOfBoundsResult));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008547 }
8548
msaboff@apple.comb644c252015-03-24 10:05:21 +00008549 void compileGetEnumeratorGenericPname()
8550 {
8551 LValue enumerator = lowCell(m_node->child1());
8552 LValue index = lowInt32(m_node->child2());
8553
fpizlo@apple.com91331742016-03-07 02:07:28 +00008554 LBasicBlock inBounds = m_out.newBlock();
8555 LBasicBlock outOfBounds = m_out.newBlock();
8556 LBasicBlock continuation = m_out.newBlock();
msaboff@apple.comb644c252015-03-24 10:05:21 +00008557
8558 m_out.branch(m_out.below(index, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_endGenericPropertyIndex)),
8559 usually(inBounds), rarely(outOfBounds));
8560
8561 LBasicBlock lastNext = m_out.appendTo(inBounds, outOfBounds);
8562 LValue storage = m_out.loadPtr(enumerator, m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector);
8563 ValueFromBlock inBoundsResult = m_out.anchor(
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00008564 m_out.loadPtr(m_out.baseIndex(m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVectorContents, storage, m_out.zeroExtPtr(index))));
msaboff@apple.comb644c252015-03-24 10:05:21 +00008565 m_out.jump(continuation);
8566
8567 m_out.appendTo(outOfBounds, continuation);
8568 ValueFromBlock outOfBoundsResult = m_out.anchor(m_out.constInt64(ValueNull));
8569 m_out.jump(continuation);
8570
8571 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008572 setJSValue(m_out.phi(Int64, inBoundsResult, outOfBoundsResult));
msaboff@apple.comb644c252015-03-24 10:05:21 +00008573 }
8574
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008575 void compileToIndexString()
8576 {
8577 LValue index = lowInt32(m_node->child1());
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008578 setJSValue(vmCall(Int64, m_out.operation(operationToIndexString), m_callFrame, index));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008579 }
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00008580
8581 void compileCheckStructureImmediate()
8582 {
basile_clement@apple.come91b66f2015-05-04 18:37:58 +00008583 LValue structure = lowCell(m_node->child1());
8584 checkStructure(
8585 structure, noValue(), BadCache, m_node->structureSet(),
sbarati@apple.com239d20b2017-01-26 23:50:58 +00008586 [this] (RegisteredStructure structure) {
basile_clement@apple.come91b66f2015-05-04 18:37:58 +00008587 return weakStructure(structure);
8588 });
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00008589 }
8590
8591 void compileMaterializeNewObject()
8592 {
8593 ObjectMaterializationData& data = m_node->objectMaterializationData();
8594
8595 // Lower the values first, to avoid creating values inside a control flow diamond.
8596
8597 Vector<LValue, 8> values;
fpizlo@apple.com280ef002016-04-05 22:13:16 +00008598 for (unsigned i = 0; i < data.m_properties.size(); ++i) {
8599 Edge edge = m_graph.varArgChild(m_node, 1 + i);
8600 switch (data.m_properties[i].kind()) {
8601 case PublicLengthPLoc:
8602 case VectorLengthPLoc:
8603 values.append(lowInt32(edge));
8604 break;
8605 default:
8606 values.append(lowJSValue(edge));
8607 break;
8608 }
8609 }
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00008610
sbarati@apple.com239d20b2017-01-26 23:50:58 +00008611 RegisteredStructureSet set = m_node->structureSet();
fpizlo@apple.com280ef002016-04-05 22:13:16 +00008612
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00008613 Vector<LBasicBlock, 1> blocks(set.size());
8614 for (unsigned i = set.size(); i--;)
fpizlo@apple.com91331742016-03-07 02:07:28 +00008615 blocks[i] = m_out.newBlock();
8616 LBasicBlock dummyDefault = m_out.newBlock();
8617 LBasicBlock outerContinuation = m_out.newBlock();
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00008618
8619 Vector<SwitchCase, 1> cases(set.size());
8620 for (unsigned i = set.size(); i--;)
sbarati@apple.com239d20b2017-01-26 23:50:58 +00008621 cases[i] = SwitchCase(weakStructure(set.at(i)), blocks[i], Weight(1));
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00008622 m_out.switchInstruction(
8623 lowCell(m_graph.varArgChild(m_node, 0)), cases, dummyDefault, Weight(0));
8624
8625 LBasicBlock outerLastNext = m_out.m_nextBlock;
8626
8627 Vector<ValueFromBlock, 1> results;
8628
8629 for (unsigned i = set.size(); i--;) {
8630 m_out.appendTo(blocks[i], i + 1 < set.size() ? blocks[i + 1] : dummyDefault);
8631
sbarati@apple.com239d20b2017-01-26 23:50:58 +00008632 RegisteredStructure structure = set.at(i);
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00008633
8634 LValue object;
8635 LValue butterfly;
8636
fpizlo@apple.com280ef002016-04-05 22:13:16 +00008637 if (structure->outOfLineCapacity() || hasIndexedProperties(structure->indexingType())) {
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00008638 size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity());
fpizlo@apple.com5fa9d962017-01-18 04:22:45 +00008639 MarkedAllocator* cellAllocator = subspaceFor<JSFinalObject>(vm())->allocatorFor(allocationSize);
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00008640 DFG_ASSERT(m_graph, m_node, cellAllocator);
fpizlo@apple.com280ef002016-04-05 22:13:16 +00008641
8642 bool hasIndexingHeader = hasIndexedProperties(structure->indexingType());
8643 unsigned indexingHeaderSize = 0;
8644 LValue indexingPayloadSizeInBytes = m_out.intPtrZero;
8645 LValue vectorLength = m_out.int32Zero;
8646 LValue publicLength = m_out.int32Zero;
8647 if (hasIndexingHeader) {
8648 indexingHeaderSize = sizeof(IndexingHeader);
8649 for (unsigned i = data.m_properties.size(); i--;) {
8650 PromotedLocationDescriptor descriptor = data.m_properties[i];
8651 switch (descriptor.kind()) {
8652 case PublicLengthPLoc:
8653 publicLength = values[i];
8654 break;
8655 case VectorLengthPLoc:
8656 vectorLength = values[i];
8657 break;
8658 default:
8659 break;
8660 }
8661 }
8662 indexingPayloadSizeInBytes =
8663 m_out.mul(m_out.zeroExtPtr(vectorLength), m_out.intPtrEight);
8664 }
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00008665
fpizlo@apple.com280ef002016-04-05 22:13:16 +00008666 LValue butterflySize = m_out.add(
8667 m_out.constIntPtr(
8668 structure->outOfLineCapacity() * sizeof(JSValue) + indexingHeaderSize),
8669 indexingPayloadSizeInBytes);
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00008670
fpizlo@apple.com91331742016-03-07 02:07:28 +00008671 LBasicBlock slowPath = m_out.newBlock();
8672 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00008673
8674 LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
8675
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00008676 ValueFromBlock noButterfly = m_out.anchor(m_out.intPtrZero);
8677
8678 LValue startOfStorage = allocateHeapCell(
fpizlo@apple.com5fa9d962017-01-18 04:22:45 +00008679 allocatorForSize(vm().auxiliarySpace, butterflySize, slowPath),
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00008680 slowPath);
fpizlo@apple.com280ef002016-04-05 22:13:16 +00008681
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00008682 LValue fastButterflyValue = m_out.add(
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00008683 startOfStorage,
8684 m_out.constIntPtr(
8685 structure->outOfLineCapacity() * sizeof(JSValue) + sizeof(IndexingHeader)));
8686
8687 ValueFromBlock haveButterfly = m_out.anchor(fastButterflyValue);
fpizlo@apple.com101a1682016-11-15 01:49:22 +00008688
fpizlo@apple.comb09568c2016-12-09 03:30:03 +00008689 splatWords(
8690 fastButterflyValue,
8691 m_out.constInt32(-structure->outOfLineCapacity() - 1),
8692 m_out.constInt32(-1),
8693 m_out.int64Zero, m_heaps.properties.atAnyNumber());
fpizlo@apple.com280ef002016-04-05 22:13:16 +00008694
8695 m_out.store32(vectorLength, fastButterflyValue, m_heaps.Butterfly_vectorLength);
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00008696
8697 LValue fastObjectValue = allocateObject(
commit-queue@webkit.org3194ff32016-11-30 20:30:16 +00008698 m_out.constIntPtr(cellAllocator), structure, fastButterflyValue, slowPath);
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00008699
8700 ValueFromBlock fastObject = m_out.anchor(fastObjectValue);
8701 ValueFromBlock fastButterfly = m_out.anchor(fastButterflyValue);
8702 m_out.jump(continuation);
8703
8704 m_out.appendTo(slowPath, continuation);
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00008705
8706 LValue butterflyValue = m_out.phi(pointerType(), noButterfly, haveButterfly);
fpizlo@apple.com6e697962015-10-12 17:56:26 +00008707
fpizlo@apple.com280ef002016-04-05 22:13:16 +00008708 LValue slowObjectValue;
8709 if (hasIndexingHeader) {
8710 slowObjectValue = lazySlowPath(
8711 [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
8712 return createLazyCallGenerator(
8713 operationNewObjectWithButterflyWithIndexingHeaderAndVectorLength,
sbarati@apple.com239d20b2017-01-26 23:50:58 +00008714 locations[0].directGPR(), CCallHelpers::TrustedImmPtr(structure.get()),
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00008715 locations[1].directGPR(), locations[2].directGPR());
fpizlo@apple.com280ef002016-04-05 22:13:16 +00008716 },
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00008717 vectorLength, butterflyValue);
fpizlo@apple.com280ef002016-04-05 22:13:16 +00008718 } else {
8719 slowObjectValue = lazySlowPath(
8720 [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
8721 return createLazyCallGenerator(
8722 operationNewObjectWithButterfly, locations[0].directGPR(),
sbarati@apple.com239d20b2017-01-26 23:50:58 +00008723 CCallHelpers::TrustedImmPtr(structure.get()), locations[1].directGPR());
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00008724 },
8725 butterflyValue);
fpizlo@apple.com280ef002016-04-05 22:13:16 +00008726 }
fpizlo@apple.com6e697962015-10-12 17:56:26 +00008727 ValueFromBlock slowObject = m_out.anchor(slowObjectValue);
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00008728 ValueFromBlock slowButterfly = m_out.anchor(
fpizlo@apple.com6e697962015-10-12 17:56:26 +00008729 m_out.loadPtr(slowObjectValue, m_heaps.JSObject_butterfly));
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00008730
8731 m_out.jump(continuation);
8732
8733 m_out.appendTo(continuation, lastNext);
8734
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008735 object = m_out.phi(pointerType(), fastObject, slowObject);
8736 butterfly = m_out.phi(pointerType(), fastButterfly, slowButterfly);
fpizlo@apple.com280ef002016-04-05 22:13:16 +00008737
8738 m_out.store32(publicLength, butterfly, m_heaps.Butterfly_publicLength);
8739
sbarati@apple.comfd407a52017-01-13 04:03:47 +00008740 initializeArrayElements(m_out.constInt32(structure->indexingType()), m_out.int32Zero, vectorLength, butterfly);
fpizlo@apple.com280ef002016-04-05 22:13:16 +00008741
8742 HashMap<int32_t, LValue, DefaultHash<int32_t>::Hash, WTF::UnsignedWithZeroKeyHashTraits<int32_t>> indexMap;
8743 Vector<int32_t> indices;
8744 for (unsigned i = data.m_properties.size(); i--;) {
8745 PromotedLocationDescriptor descriptor = data.m_properties[i];
8746 if (descriptor.kind() != IndexedPropertyPLoc)
8747 continue;
8748 int32_t index = static_cast<int32_t>(descriptor.info());
8749
8750 auto result = indexMap.add(index, values[i]);
8751 DFG_ASSERT(m_graph, m_node, result); // Duplicates are illegal.
8752
8753 indices.append(index);
8754 }
8755
8756 if (!indices.isEmpty()) {
8757 std::sort(indices.begin(), indices.end());
8758
8759 Vector<LBasicBlock> blocksWithStores(indices.size());
8760 Vector<LBasicBlock> blocksWithChecks(indices.size());
8761
8762 for (unsigned i = indices.size(); i--;) {
8763 blocksWithStores[i] = m_out.newBlock();
8764 blocksWithChecks[i] = m_out.newBlock(); // blocksWithChecks[0] is the continuation.
8765 }
8766
8767 LBasicBlock indexLastNext = m_out.m_nextBlock;
8768
8769 for (unsigned i = indices.size(); i--;) {
8770 int32_t index = indices[i];
8771 LValue value = indexMap.get(index);
8772
8773 m_out.branch(
8774 m_out.below(m_out.constInt32(index), publicLength),
8775 unsure(blocksWithStores[i]), unsure(blocksWithChecks[i]));
8776
8777 m_out.appendTo(blocksWithStores[i], blocksWithChecks[i]);
8778
8779 // This has to type-check and convert its inputs, but it cannot do so in a
8780 // way that updates AI. That's a bit annoying, but if you think about how
8781 // sinking works, it's actually not a bad thing. We are virtually guaranteed
8782 // that these type checks will not fail, since the type checks that guarded
8783 // the original stores to the array are still somewhere above this point.
8784 Output::StoreType storeType;
8785 IndexedAbstractHeap* heap;
8786 switch (structure->indexingType()) {
8787 case ALL_INT32_INDEXING_TYPES:
8788 // FIXME: This could use the proven type if we had the Edge for the
8789 // value. https://bugs.webkit.org/show_bug.cgi?id=155311
8790 speculate(BadType, noValue(), nullptr, isNotInt32(value));
8791 storeType = Output::Store64;
8792 heap = &m_heaps.indexedInt32Properties;
8793 break;
8794
8795 case ALL_DOUBLE_INDEXING_TYPES: {
8796 // FIXME: If the source is ValueRep, we should avoid emitting any
8797 // checks. We could also avoid emitting checks if we had the Edge of
8798 // this value. https://bugs.webkit.org/show_bug.cgi?id=155311
8799
8800 LBasicBlock intCase = m_out.newBlock();
8801 LBasicBlock doubleCase = m_out.newBlock();
8802 LBasicBlock continuation = m_out.newBlock();
8803
8804 m_out.branch(isInt32(value), unsure(intCase), unsure(doubleCase));
8805
8806 LBasicBlock lastNext = m_out.appendTo(intCase, doubleCase);
8807
8808 ValueFromBlock intResult =
8809 m_out.anchor(m_out.intToDouble(unboxInt32(value)));
8810 m_out.jump(continuation);
8811
8812 m_out.appendTo(doubleCase, continuation);
8813
8814 speculate(BadType, noValue(), nullptr, isNumber(value));
8815 ValueFromBlock doubleResult = m_out.anchor(unboxDouble(value));
8816 m_out.jump(continuation);
8817
8818 m_out.appendTo(continuation, lastNext);
8819 value = m_out.phi(Double, intResult, doubleResult);
8820 storeType = Output::StoreDouble;
8821 heap = &m_heaps.indexedDoubleProperties;
8822 break;
8823 }
8824
8825 case ALL_CONTIGUOUS_INDEXING_TYPES:
8826 storeType = Output::Store64;
8827 heap = &m_heaps.indexedContiguousProperties;
8828 break;
8829
8830 default:
8831 DFG_CRASH(m_graph, m_node, "Invalid indexing type");
8832 break;
8833 }
8834
8835 m_out.store(value, m_out.address(butterfly, heap->at(index)), storeType);
8836
8837 m_out.jump(blocksWithChecks[i]);
8838 m_out.appendTo(
8839 blocksWithChecks[i], i ? blocksWithStores[i - 1] : indexLastNext);
8840 }
8841 }
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00008842 } else {
8843 // In the easy case where we can do a one-shot allocation, we simply allocate the
8844 // object to directly have the desired structure.
8845 object = allocateObject(structure);
8846 butterfly = nullptr; // Don't have one, don't need one.
8847 }
fpizlo@apple.com101a1682016-11-15 01:49:22 +00008848
8849 BitVector setInlineOffsets;
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00008850 for (PropertyMapEntry entry : structure->getPropertiesConcurrently()) {
8851 for (unsigned i = data.m_properties.size(); i--;) {
fpizlo@apple.com280ef002016-04-05 22:13:16 +00008852 PromotedLocationDescriptor descriptor = data.m_properties[i];
8853 if (descriptor.kind() != NamedPropertyPLoc)
8854 continue;
8855 if (m_graph.identifiers()[descriptor.info()] != entry.key)
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00008856 continue;
8857
fpizlo@apple.com101a1682016-11-15 01:49:22 +00008858 LValue base;
8859 if (isInlineOffset(entry.offset)) {
8860 setInlineOffsets.set(entry.offset);
8861 base = object;
8862 } else
8863 base = butterfly;
fpizlo@apple.com280ef002016-04-05 22:13:16 +00008864 storeProperty(values[i], base, descriptor.info(), entry.offset);
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00008865 break;
8866 }
8867 }
fpizlo@apple.com101a1682016-11-15 01:49:22 +00008868 for (unsigned i = structure->inlineCapacity(); i--;) {
8869 if (!setInlineOffsets.get(i))
8870 m_out.store64(m_out.int64Zero, m_out.address(m_heaps.properties.atAnyNumber(), object, offsetRelativeToBase(i)));
8871 }
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00008872
8873 results.append(m_out.anchor(object));
8874 m_out.jump(outerContinuation);
8875 }
8876
8877 m_out.appendTo(dummyDefault, outerContinuation);
8878 m_out.unreachable();
8879
8880 m_out.appendTo(outerContinuation, outerLastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008881 setJSValue(m_out.phi(pointerType(), results));
fpizlo@apple.com101a1682016-11-15 01:49:22 +00008882 mutatorFence();
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00008883 }
fpizlo@apple.coma398a562014-08-06 21:32:55 +00008884
basile_clement@apple.com2ca1f7b2015-05-05 16:34:21 +00008885 void compileMaterializeCreateActivation()
8886 {
8887 ObjectMaterializationData& data = m_node->objectMaterializationData();
8888
8889 Vector<LValue, 8> values;
8890 for (unsigned i = 0; i < data.m_properties.size(); ++i)
basile_clement@apple.comd7930292015-07-13 23:27:30 +00008891 values.append(lowJSValue(m_graph.varArgChild(m_node, 2 + i)));
basile_clement@apple.com2ca1f7b2015-05-05 16:34:21 +00008892
basile_clement@apple.comd7930292015-07-13 23:27:30 +00008893 LValue scope = lowCell(m_graph.varArgChild(m_node, 1));
saambarati1@gmail.com402b5852015-05-22 02:39:25 +00008894 SymbolTable* table = m_node->castOperand<SymbolTable*>();
basile_clement@apple.comd7930292015-07-13 23:27:30 +00008895 ASSERT(table == m_graph.varArgChild(m_node, 0)->castConstant<SymbolTable*>());
sbarati@apple.com239d20b2017-01-26 23:50:58 +00008896 RegisteredStructure structure = m_graph.registerStructure(m_graph.globalObjectFor(m_node->origin.semantic)->activationStructure());
basile_clement@apple.com2ca1f7b2015-05-05 16:34:21 +00008897
fpizlo@apple.com91331742016-03-07 02:07:28 +00008898 LBasicBlock slowPath = m_out.newBlock();
8899 LBasicBlock continuation = m_out.newBlock();
basile_clement@apple.com2ca1f7b2015-05-05 16:34:21 +00008900
8901 LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
8902
8903 LValue fastObject = allocateObject<JSLexicalEnvironment>(
8904 JSLexicalEnvironment::allocationSize(table), structure, m_out.intPtrZero, slowPath);
8905
8906 m_out.storePtr(scope, fastObject, m_heaps.JSScope_next);
8907 m_out.storePtr(weakPointer(table), fastObject, m_heaps.JSSymbolTableObject_symbolTable);
8908
basile_clement@apple.com2ca1f7b2015-05-05 16:34:21 +00008909
8910 ValueFromBlock fastResult = m_out.anchor(fastObject);
8911 m_out.jump(continuation);
8912
8913 m_out.appendTo(slowPath, continuation);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00008914 // We ensure allocation sinking explictly sets bottom values for all field members.
8915 // Therefore, it doesn't matter what JSValue we pass in as the initialization value
8916 // because all fields will be overwritten.
8917 // FIXME: It may be worth creating an operation that calls a constructor on JSLexicalEnvironment that
8918 // doesn't initialize every slot because we are guaranteed to do that here.
fpizlo@apple.com6e697962015-10-12 17:56:26 +00008919 LValue callResult = lazySlowPath(
8920 [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
8921 return createLazyCallGenerator(
8922 operationCreateActivationDirect, locations[0].directGPR(),
sbarati@apple.com239d20b2017-01-26 23:50:58 +00008923 CCallHelpers::TrustedImmPtr(structure.get()), locations[1].directGPR(),
fpizlo@apple.com6e697962015-10-12 17:56:26 +00008924 CCallHelpers::TrustedImmPtr(table),
8925 CCallHelpers::TrustedImm64(JSValue::encode(jsUndefined())));
8926 }, scope);
basile_clement@apple.com2ca1f7b2015-05-05 16:34:21 +00008927 ValueFromBlock slowResult = m_out.anchor(callResult);
8928 m_out.jump(continuation);
8929
8930 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00008931 LValue activation = m_out.phi(pointerType(), fastResult, slowResult);
saambarati1@gmail.com402b5852015-05-22 02:39:25 +00008932 RELEASE_ASSERT(data.m_properties.size() == table->scopeSize());
basile_clement@apple.com2ca1f7b2015-05-05 16:34:21 +00008933 for (unsigned i = 0; i < data.m_properties.size(); ++i) {
fpizlo@apple.com280ef002016-04-05 22:13:16 +00008934 PromotedLocationDescriptor descriptor = data.m_properties[i];
8935 ASSERT(descriptor.kind() == ClosureVarPLoc);
8936 m_out.store64(
8937 values[i], activation,
8938 m_heaps.JSEnvironmentRecord_variables[descriptor.info()]);
basile_clement@apple.com2ca1f7b2015-05-05 16:34:21 +00008939 }
saambarati1@gmail.com402b5852015-05-22 02:39:25 +00008940
8941 if (validationEnabled()) {
8942 // Validate to make sure every slot in the scope has one value.
fpizlo@apple.com171d06f2016-11-15 23:21:50 +00008943 ConcurrentJSLocker locker(table->m_lock);
saambarati1@gmail.com402b5852015-05-22 02:39:25 +00008944 for (auto iter = table->begin(locker), end = table->end(locker); iter != end; ++iter) {
8945 bool found = false;
8946 for (unsigned i = 0; i < data.m_properties.size(); ++i) {
fpizlo@apple.com280ef002016-04-05 22:13:16 +00008947 PromotedLocationDescriptor descriptor = data.m_properties[i];
8948 ASSERT(descriptor.kind() == ClosureVarPLoc);
8949 if (iter->value.scopeOffset().offset() == descriptor.info()) {
saambarati1@gmail.com402b5852015-05-22 02:39:25 +00008950 found = true;
8951 break;
8952 }
8953 }
utatane.tea@gmail.com8268d392015-05-23 18:41:53 +00008954 ASSERT_UNUSED(found, found);
saambarati1@gmail.com402b5852015-05-22 02:39:25 +00008955 }
8956 }
8957
fpizlo@apple.com101a1682016-11-15 01:49:22 +00008958 mutatorFence();
basile_clement@apple.com2ca1f7b2015-05-05 16:34:21 +00008959 setJSValue(activation);
8960 }
8961
mark.lam@apple.com528ebe92015-08-19 21:18:15 +00008962 void compileCheckWatchdogTimer()
8963 {
fpizlo@apple.com91331742016-03-07 02:07:28 +00008964 LBasicBlock timerDidFire = m_out.newBlock();
8965 LBasicBlock continuation = m_out.newBlock();
mark.lam@apple.com528ebe92015-08-19 21:18:15 +00008966
sbarati@apple.com390337b2015-12-07 22:03:48 +00008967 LValue state = m_out.load8ZeroExt32(m_out.absolute(vm().watchdog()->timerDidFireAddress()));
benjamin@webkit.org2e864d22015-11-17 06:20:21 +00008968 m_out.branch(m_out.isZero32(state),
mark.lam@apple.com528ebe92015-08-19 21:18:15 +00008969 usually(continuation), rarely(timerDidFire));
8970
8971 LBasicBlock lastNext = m_out.appendTo(timerDidFire, continuation);
8972
fpizlo@apple.com6e697962015-10-12 17:56:26 +00008973 lazySlowPath(
8974 [=] (const Vector<Location>&) -> RefPtr<LazySlowPath::Generator> {
8975 return createLazyCallGenerator(operationHandleWatchdogTimer, InvalidGPRReg);
8976 });
mark.lam@apple.com528ebe92015-08-19 21:18:15 +00008977 m_out.jump(continuation);
8978
8979 m_out.appendTo(continuation, lastNext);
8980 }
8981
fpizlo@apple.comdbd768a2016-02-29 18:05:17 +00008982 void compileRegExpExec()
8983 {
fpizlo@apple.com7518ba22016-03-06 20:11:09 +00008984 LValue globalObject = lowCell(m_node->child1());
8985
8986 if (m_node->child2().useKind() == RegExpObjectUse) {
8987 LValue base = lowRegExpObject(m_node->child2());
fpizlo@apple.com7fdfeed2016-03-06 00:48:11 +00008988
fpizlo@apple.com7518ba22016-03-06 20:11:09 +00008989 if (m_node->child3().useKind() == StringUse) {
8990 LValue argument = lowString(m_node->child3());
fpizlo@apple.com7fdfeed2016-03-06 00:48:11 +00008991 LValue result = vmCall(
fpizlo@apple.com7518ba22016-03-06 20:11:09 +00008992 Int64, m_out.operation(operationRegExpExecString), m_callFrame, globalObject,
8993 base, argument);
fpizlo@apple.com7fdfeed2016-03-06 00:48:11 +00008994 setJSValue(result);
8995 return;
8996 }
8997
fpizlo@apple.com7518ba22016-03-06 20:11:09 +00008998 LValue argument = lowJSValue(m_node->child3());
8999 LValue result = vmCall(
9000 Int64, m_out.operation(operationRegExpExec), m_callFrame, globalObject, base,
9001 argument);
9002 setJSValue(result);
fpizlo@apple.com239b0782016-03-03 05:58:59 +00009003 return;
9004 }
9005
fpizlo@apple.com7518ba22016-03-06 20:11:09 +00009006 LValue base = lowJSValue(m_node->child2());
9007 LValue argument = lowJSValue(m_node->child3());
9008 LValue result = vmCall(
9009 Int64, m_out.operation(operationRegExpExecGeneric), m_callFrame, globalObject, base,
9010 argument);
9011 setJSValue(result);
fpizlo@apple.comdbd768a2016-02-29 18:05:17 +00009012 }
9013
9014 void compileRegExpTest()
9015 {
fpizlo@apple.com7518ba22016-03-06 20:11:09 +00009016 LValue globalObject = lowCell(m_node->child1());
9017
9018 if (m_node->child2().useKind() == RegExpObjectUse) {
9019 LValue base = lowRegExpObject(m_node->child2());
fpizlo@apple.com7fdfeed2016-03-06 00:48:11 +00009020
fpizlo@apple.com7518ba22016-03-06 20:11:09 +00009021 if (m_node->child3().useKind() == StringUse) {
9022 LValue argument = lowString(m_node->child3());
fpizlo@apple.com7fdfeed2016-03-06 00:48:11 +00009023 LValue result = vmCall(
fpizlo@apple.com7518ba22016-03-06 20:11:09 +00009024 Int32, m_out.operation(operationRegExpTestString), m_callFrame, globalObject,
9025 base, argument);
fpizlo@apple.com7fdfeed2016-03-06 00:48:11 +00009026 setBoolean(result);
9027 return;
9028 }
9029
fpizlo@apple.com7518ba22016-03-06 20:11:09 +00009030 LValue argument = lowJSValue(m_node->child3());
9031 LValue result = vmCall(
9032 Int32, m_out.operation(operationRegExpTest), m_callFrame, globalObject, base,
9033 argument);
9034 setBoolean(result);
fpizlo@apple.com239b0782016-03-03 05:58:59 +00009035 return;
9036 }
9037
fpizlo@apple.com7518ba22016-03-06 20:11:09 +00009038 LValue base = lowJSValue(m_node->child2());
9039 LValue argument = lowJSValue(m_node->child3());
9040 LValue result = vmCall(
9041 Int32, m_out.operation(operationRegExpTestGeneric), m_callFrame, globalObject, base,
9042 argument);
9043 setBoolean(result);
fpizlo@apple.comdbd768a2016-02-29 18:05:17 +00009044 }
9045
9046 void compileNewRegexp()
9047 {
sbarati@apple.com239d20b2017-01-26 23:50:58 +00009048 FrozenValue* regexp = m_node->cellOperand();
9049 ASSERT(regexp->cell()->inherits(RegExp::info()));
fpizlo@apple.comdbd768a2016-02-29 18:05:17 +00009050 LValue result = vmCall(
9051 pointerType(),
9052 m_out.operation(operationNewRegexp), m_callFrame,
sbarati@apple.com239d20b2017-01-26 23:50:58 +00009053 frozenPointer(regexp));
fpizlo@apple.comdbd768a2016-02-29 18:05:17 +00009054
9055 setJSValue(result);
9056 }
9057
mark.lam@apple.com47c2f142016-03-16 18:16:32 +00009058 void compileSetFunctionName()
9059 {
fpizlo@apple.com994d4532016-07-03 19:34:55 +00009060 vmCall(Void, m_out.operation(operationSetFunctionName), m_callFrame,
mark.lam@apple.com47c2f142016-03-16 18:16:32 +00009061 lowCell(m_node->child1()), lowJSValue(m_node->child2()));
9062 }
9063
fpizlo@apple.come799b862016-03-01 21:18:42 +00009064 void compileStringReplace()
9065 {
9066 if (m_node->child1().useKind() == StringUse
9067 && m_node->child2().useKind() == RegExpObjectUse
9068 && m_node->child3().useKind() == StringUse) {
fpizlo@apple.com341b0d82016-03-01 23:35:05 +00009069
9070 if (JSString* replace = m_node->child3()->dynamicCastConstant<JSString*>()) {
9071 if (!replace->length()) {
9072 LValue string = lowString(m_node->child1());
fpizlo@apple.comef515142016-03-04 06:36:24 +00009073 LValue regExp = lowRegExpObject(m_node->child2());
fpizlo@apple.com341b0d82016-03-01 23:35:05 +00009074
9075 LValue result = vmCall(
9076 Int64, m_out.operation(operationStringProtoFuncReplaceRegExpEmptyStr),
9077 m_callFrame, string, regExp);
9078
9079 setJSValue(result);
9080 return;
9081 }
9082 }
fpizlo@apple.come799b862016-03-01 21:18:42 +00009083
9084 LValue string = lowString(m_node->child1());
fpizlo@apple.comef515142016-03-04 06:36:24 +00009085 LValue regExp = lowRegExpObject(m_node->child2());
fpizlo@apple.come799b862016-03-01 21:18:42 +00009086 LValue replace = lowString(m_node->child3());
9087
9088 LValue result = vmCall(
9089 Int64, m_out.operation(operationStringProtoFuncReplaceRegExpString),
9090 m_callFrame, string, regExp, replace);
9091
9092 setJSValue(result);
9093 return;
9094 }
msaboff@apple.comdf55aa22016-04-27 20:37:49 +00009095
9096 LValue search;
9097 if (m_node->child2().useKind() == StringUse)
9098 search = lowString(m_node->child2());
9099 else
9100 search = lowJSValue(m_node->child2());
9101
fpizlo@apple.come799b862016-03-01 21:18:42 +00009102 LValue result = vmCall(
9103 Int64, m_out.operation(operationStringProtoFuncReplaceGeneric), m_callFrame,
msaboff@apple.comdf55aa22016-04-27 20:37:49 +00009104 lowJSValue(m_node->child1()), search,
fpizlo@apple.come799b862016-03-01 21:18:42 +00009105 lowJSValue(m_node->child3()));
9106
9107 setJSValue(result);
9108 }
9109
fpizlo@apple.comef515142016-03-04 06:36:24 +00009110 void compileGetRegExpObjectLastIndex()
9111 {
9112 setJSValue(m_out.load64(lowRegExpObject(m_node->child1()), m_heaps.RegExpObject_lastIndex));
9113 }
9114
9115 void compileSetRegExpObjectLastIndex()
9116 {
9117 LValue regExp = lowRegExpObject(m_node->child1());
9118 LValue value = lowJSValue(m_node->child2());
9119
9120 speculate(
9121 ExoticObjectMode, noValue(), nullptr,
9122 m_out.isZero32(m_out.load8ZeroExt32(regExp, m_heaps.RegExpObject_lastIndexIsWritable)));
9123
9124 m_out.store64(value, regExp, m_heaps.RegExpObject_lastIndex);
9125 }
fpizlo@apple.com39303e02016-04-05 22:17:35 +00009126
9127 void compileLogShadowChickenPrologue()
9128 {
sbarati@apple.comce5b05e2016-05-16 23:31:39 +00009129 LValue packet = ensureShadowChickenPacket();
9130 LValue scope = lowCell(m_node->child1());
9131
fpizlo@apple.com39303e02016-04-05 22:17:35 +00009132 m_out.storePtr(m_callFrame, packet, m_heaps.ShadowChicken_Packet_frame);
9133 m_out.storePtr(m_out.loadPtr(addressFor(0)), packet, m_heaps.ShadowChicken_Packet_callerFrame);
mark.lam@apple.com2bd89342016-07-08 22:58:15 +00009134 m_out.storePtr(m_out.loadPtr(payloadFor(CallFrameSlot::callee)), packet, m_heaps.ShadowChicken_Packet_callee);
sbarati@apple.comce5b05e2016-05-16 23:31:39 +00009135 m_out.storePtr(scope, packet, m_heaps.ShadowChicken_Packet_scope);
fpizlo@apple.com39303e02016-04-05 22:17:35 +00009136 }
9137
9138 void compileLogShadowChickenTail()
9139 {
sbarati@apple.comce5b05e2016-05-16 23:31:39 +00009140 LValue packet = ensureShadowChickenPacket();
9141 LValue thisValue = lowJSValue(m_node->child1());
9142 LValue scope = lowCell(m_node->child2());
9143 CallSiteIndex callSiteIndex = m_ftlState.jitCode->common.addCodeOrigin(m_node->origin.semantic);
fpizlo@apple.com39303e02016-04-05 22:17:35 +00009144
9145 m_out.storePtr(m_callFrame, packet, m_heaps.ShadowChicken_Packet_frame);
sbarati@apple.com239d20b2017-01-26 23:50:58 +00009146 m_out.storePtr(m_out.constIntPtr(bitwise_cast<intptr_t>(ShadowChicken::Packet::tailMarker())), packet, m_heaps.ShadowChicken_Packet_callee);
sbarati@apple.comce5b05e2016-05-16 23:31:39 +00009147 m_out.store64(thisValue, packet, m_heaps.ShadowChicken_Packet_thisValue);
9148 m_out.storePtr(scope, packet, m_heaps.ShadowChicken_Packet_scope);
sbarati@apple.com239d20b2017-01-26 23:50:58 +00009149 // We don't want the CodeBlock to have a weak pointer to itself because
9150 // that would cause it to always get collected.
9151 m_out.storePtr(m_out.constIntPtr(bitwise_cast<intptr_t>(codeBlock())), packet, m_heaps.ShadowChicken_Packet_codeBlock);
sbarati@apple.comce5b05e2016-05-16 23:31:39 +00009152 m_out.store32(m_out.constInt32(callSiteIndex.bits()), packet, m_heaps.ShadowChicken_Packet_callSiteIndex);
fpizlo@apple.com39303e02016-04-05 22:17:35 +00009153 }
fpizlo@apple.comef515142016-03-04 06:36:24 +00009154
fpizlo@apple.com280ef002016-04-05 22:13:16 +00009155 void compileRecordRegExpCachedResult()
9156 {
9157 Edge constructorEdge = m_graph.varArgChild(m_node, 0);
9158 Edge regExpEdge = m_graph.varArgChild(m_node, 1);
9159 Edge stringEdge = m_graph.varArgChild(m_node, 2);
9160 Edge startEdge = m_graph.varArgChild(m_node, 3);
9161 Edge endEdge = m_graph.varArgChild(m_node, 4);
9162
9163 LValue constructor = lowCell(constructorEdge);
9164 LValue regExp = lowCell(regExpEdge);
9165 LValue string = lowCell(stringEdge);
9166 LValue start = lowInt32(startEdge);
9167 LValue end = lowInt32(endEdge);
9168
9169 m_out.storePtr(regExp, constructor, m_heaps.RegExpConstructor_cachedResult_lastRegExp);
9170 m_out.storePtr(string, constructor, m_heaps.RegExpConstructor_cachedResult_lastInput);
9171 m_out.store32(start, constructor, m_heaps.RegExpConstructor_cachedResult_result_start);
9172 m_out.store32(end, constructor, m_heaps.RegExpConstructor_cachedResult_result_end);
9173 m_out.store32As8(
9174 m_out.constInt32(0),
9175 m_out.address(constructor, m_heaps.RegExpConstructor_cachedResult_reified));
9176 }
fpizlo@apple.com0e09bc52014-02-20 20:37:03 +00009177
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00009178 struct ArgumentsLength {
9179 ArgumentsLength()
9180 : isKnown(false)
9181 , known(UINT_MAX)
9182 , value(nullptr)
9183 {
9184 }
9185
9186 bool isKnown;
9187 unsigned known;
9188 LValue value;
9189 };
9190 ArgumentsLength getArgumentsLength(InlineCallFrame* inlineCallFrame)
9191 {
9192 ArgumentsLength length;
9193
9194 if (inlineCallFrame && !inlineCallFrame->isVarargs()) {
9195 length.known = inlineCallFrame->arguments.size() - 1;
9196 length.isKnown = true;
9197 length.value = m_out.constInt32(length.known);
9198 } else {
9199 length.known = UINT_MAX;
9200 length.isKnown = false;
9201
9202 VirtualRegister argumentCountRegister;
9203 if (!inlineCallFrame)
mark.lam@apple.com2bd89342016-07-08 22:58:15 +00009204 argumentCountRegister = VirtualRegister(CallFrameSlot::argumentCount);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00009205 else
9206 argumentCountRegister = inlineCallFrame->argumentCountRegister;
9207 length.value = m_out.sub(m_out.load32(payloadFor(argumentCountRegister)), m_out.int32One);
9208 }
9209
9210 return length;
9211 }
9212
9213 ArgumentsLength getArgumentsLength()
9214 {
9215 return getArgumentsLength(m_node->origin.semantic.inlineCallFrame);
9216 }
9217
9218 LValue getCurrentCallee()
9219 {
9220 if (InlineCallFrame* frame = m_node->origin.semantic.inlineCallFrame) {
9221 if (frame->isClosureCall)
9222 return m_out.loadPtr(addressFor(frame->calleeRecovery.virtualRegister()));
9223 return weakPointer(frame->calleeRecovery.constant().asCell());
9224 }
mark.lam@apple.com2bd89342016-07-08 22:58:15 +00009225 return m_out.loadPtr(addressFor(CallFrameSlot::callee));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00009226 }
9227
sbarati@apple.com7a74ce72016-11-01 20:03:03 +00009228 LValue getArgumentsStart(InlineCallFrame* inlineCallFrame, unsigned offset = 0)
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00009229 {
sbarati@apple.com7a74ce72016-11-01 20:03:03 +00009230 VirtualRegister start = AssemblyHelpers::argumentsStart(inlineCallFrame) + offset;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00009231 return addressFor(start).value();
9232 }
9233
9234 LValue getArgumentsStart()
9235 {
9236 return getArgumentsStart(m_node->origin.semantic.inlineCallFrame);
9237 }
9238
basile_clement@apple.come91b66f2015-05-04 18:37:58 +00009239 template<typename Functor>
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00009240 void checkStructure(
basile_clement@apple.come91b66f2015-05-04 18:37:58 +00009241 LValue structureDiscriminant, const FormattedValue& formattedValue, ExitKind exitKind,
sbarati@apple.com239d20b2017-01-26 23:50:58 +00009242 RegisteredStructureSet set, const Functor& weakStructureDiscriminant)
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00009243 {
basile_clement@apple.com50af4b82015-08-15 05:00:57 +00009244 if (set.isEmpty()) {
9245 terminate(exitKind);
9246 return;
9247 }
9248
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00009249 if (set.size() == 1) {
9250 speculate(
9251 exitKind, formattedValue, 0,
basile_clement@apple.come91b66f2015-05-04 18:37:58 +00009252 m_out.notEqual(structureDiscriminant, weakStructureDiscriminant(set[0])));
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00009253 return;
9254 }
9255
fpizlo@apple.com91331742016-03-07 02:07:28 +00009256 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00009257
9258 LBasicBlock lastNext = m_out.insertNewBlocksBefore(continuation);
9259 for (unsigned i = 0; i < set.size() - 1; ++i) {
fpizlo@apple.com91331742016-03-07 02:07:28 +00009260 LBasicBlock nextStructure = m_out.newBlock();
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00009261 m_out.branch(
basile_clement@apple.come91b66f2015-05-04 18:37:58 +00009262 m_out.equal(structureDiscriminant, weakStructureDiscriminant(set[i])),
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00009263 unsure(continuation), unsure(nextStructure));
9264 m_out.appendTo(nextStructure);
9265 }
9266
9267 speculate(
9268 exitKind, formattedValue, 0,
basile_clement@apple.come91b66f2015-05-04 18:37:58 +00009269 m_out.notEqual(structureDiscriminant, weakStructureDiscriminant(set.last())));
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +00009270
9271 m_out.jump(continuation);
9272 m_out.appendTo(continuation, lastNext);
9273 }
9274
fpizlo@apple.com29594fe2014-03-21 00:32:37 +00009275 LValue numberOrNotCellToInt32(Edge edge, LValue value)
9276 {
fpizlo@apple.com91331742016-03-07 02:07:28 +00009277 LBasicBlock intCase = m_out.newBlock();
9278 LBasicBlock notIntCase = m_out.newBlock();
fpizlo@apple.com29594fe2014-03-21 00:32:37 +00009279 LBasicBlock doubleCase = 0;
9280 LBasicBlock notNumberCase = 0;
9281 if (edge.useKind() == NotCellUse) {
fpizlo@apple.com91331742016-03-07 02:07:28 +00009282 doubleCase = m_out.newBlock();
9283 notNumberCase = m_out.newBlock();
fpizlo@apple.com29594fe2014-03-21 00:32:37 +00009284 }
fpizlo@apple.com91331742016-03-07 02:07:28 +00009285 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com29594fe2014-03-21 00:32:37 +00009286
9287 Vector<ValueFromBlock> results;
9288
9289 m_out.branch(isNotInt32(value), unsure(notIntCase), unsure(intCase));
9290
9291 LBasicBlock lastNext = m_out.appendTo(intCase, notIntCase);
9292 results.append(m_out.anchor(unboxInt32(value)));
9293 m_out.jump(continuation);
9294
9295 if (edge.useKind() == NumberUse) {
9296 m_out.appendTo(notIntCase, continuation);
fpizlo@apple.combeef4522014-04-16 22:44:00 +00009297 FTL_TYPE_CHECK(jsValueValue(value), edge, SpecBytecodeNumber, isCellOrMisc(value));
fpizlo@apple.com29594fe2014-03-21 00:32:37 +00009298 results.append(m_out.anchor(doubleToInt32(unboxDouble(value))));
9299 m_out.jump(continuation);
9300 } else {
9301 m_out.appendTo(notIntCase, doubleCase);
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00009302 m_out.branch(
9303 isCellOrMisc(value, provenType(edge)), unsure(notNumberCase), unsure(doubleCase));
fpizlo@apple.com29594fe2014-03-21 00:32:37 +00009304
9305 m_out.appendTo(doubleCase, notNumberCase);
9306 results.append(m_out.anchor(doubleToInt32(unboxDouble(value))));
9307 m_out.jump(continuation);
9308
9309 m_out.appendTo(notNumberCase, continuation);
9310
9311 FTL_TYPE_CHECK(jsValueValue(value), edge, ~SpecCell, isCell(value));
9312
9313 LValue specialResult = m_out.select(
9314 m_out.equal(value, m_out.constInt64(JSValue::encode(jsBoolean(true)))),
9315 m_out.int32One, m_out.int32Zero);
9316 results.append(m_out.anchor(specialResult));
9317 m_out.jump(continuation);
9318 }
9319
9320 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00009321 return m_out.phi(Int32, results);
fpizlo@apple.com29594fe2014-03-21 00:32:37 +00009322 }
fpizlo@apple.com12835772015-09-21 20:49:04 +00009323
9324 void checkInferredType(Edge edge, LValue value, const InferredType::Descriptor& type)
9325 {
9326 // This cannot use FTL_TYPE_CHECK or typeCheck() because it is called partially, as in a node like:
9327 //
9328 // MultiPutByOffset(...)
9329 //
9330 // may be lowered to:
9331 //
9332 // switch (object->structure) {
9333 // case 42:
9334 // checkInferredType(..., type1);
9335 // ...
9336 // break;
9337 // case 43:
9338 // checkInferredType(..., type2);
9339 // ...
9340 // break;
9341 // }
9342 //
9343 // where type1 and type2 are different. Using typeCheck() would mean that the edge would be
9344 // filtered by type1 & type2, instead of type1 | type2.
9345
9346 switch (type.kind()) {
9347 case InferredType::Bottom:
9348 speculate(BadType, jsValueValue(value), edge.node(), m_out.booleanTrue);
9349 return;
9350
9351 case InferredType::Boolean:
9352 speculate(BadType, jsValueValue(value), edge.node(), isNotBoolean(value, provenType(edge)));
9353 return;
9354
9355 case InferredType::Other:
9356 speculate(BadType, jsValueValue(value), edge.node(), isNotOther(value, provenType(edge)));
9357 return;
9358
9359 case InferredType::Int32:
9360 speculate(BadType, jsValueValue(value), edge.node(), isNotInt32(value, provenType(edge)));
9361 return;
9362
9363 case InferredType::Number:
9364 speculate(BadType, jsValueValue(value), edge.node(), isNotNumber(value, provenType(edge)));
9365 return;
9366
9367 case InferredType::String:
9368 speculate(BadType, jsValueValue(value), edge.node(), isNotCell(value, provenType(edge)));
9369 speculate(BadType, jsValueValue(value), edge.node(), isNotString(value, provenType(edge)));
9370 return;
9371
utatane.tea@gmail.com618381f2015-10-13 02:09:34 +00009372 case InferredType::Symbol:
9373 speculate(BadType, jsValueValue(value), edge.node(), isNotCell(value, provenType(edge)));
9374 speculate(BadType, jsValueValue(value), edge.node(), isNotSymbol(value, provenType(edge)));
9375 return;
9376
sbarati@apple.com239d20b2017-01-26 23:50:58 +00009377 case InferredType::ObjectWithStructure: {
9378 RegisteredStructure structure = m_graph.registerStructure(type.structure());
fpizlo@apple.com12835772015-09-21 20:49:04 +00009379 speculate(BadType, jsValueValue(value), edge.node(), isNotCell(value, provenType(edge)));
sbarati@apple.com239d20b2017-01-26 23:50:58 +00009380 if (!abstractValue(edge).m_structure.isSubsetOf(RegisteredStructureSet(structure))) {
fpizlo@apple.com12835772015-09-21 20:49:04 +00009381 speculate(
9382 BadType, jsValueValue(value), edge.node(),
9383 m_out.notEqual(
9384 m_out.load32(value, m_heaps.JSCell_structureID),
sbarati@apple.com239d20b2017-01-26 23:50:58 +00009385 weakStructureID(structure)));
fpizlo@apple.com12835772015-09-21 20:49:04 +00009386 }
9387 return;
sbarati@apple.com239d20b2017-01-26 23:50:58 +00009388 }
fpizlo@apple.com12835772015-09-21 20:49:04 +00009389
9390 case InferredType::ObjectWithStructureOrOther: {
fpizlo@apple.com91331742016-03-07 02:07:28 +00009391 LBasicBlock cellCase = m_out.newBlock();
9392 LBasicBlock notCellCase = m_out.newBlock();
9393 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com12835772015-09-21 20:49:04 +00009394
9395 m_out.branch(isCell(value, provenType(edge)), unsure(cellCase), unsure(notCellCase));
9396
9397 LBasicBlock lastNext = m_out.appendTo(cellCase, notCellCase);
9398
sbarati@apple.com239d20b2017-01-26 23:50:58 +00009399 RegisteredStructure structure = m_graph.registerStructure(type.structure());
9400 if (!abstractValue(edge).m_structure.isSubsetOf(RegisteredStructureSet(structure))) {
fpizlo@apple.com12835772015-09-21 20:49:04 +00009401 speculate(
9402 BadType, jsValueValue(value), edge.node(),
9403 m_out.notEqual(
9404 m_out.load32(value, m_heaps.JSCell_structureID),
sbarati@apple.com239d20b2017-01-26 23:50:58 +00009405 weakStructureID(structure)));
fpizlo@apple.com12835772015-09-21 20:49:04 +00009406 }
9407
9408 m_out.jump(continuation);
9409
9410 m_out.appendTo(notCellCase, continuation);
9411
9412 speculate(
9413 BadType, jsValueValue(value), edge.node(),
9414 isNotOther(value, provenType(edge) & ~SpecCell));
9415
9416 m_out.jump(continuation);
9417
9418 m_out.appendTo(continuation, lastNext);
9419 return;
9420 }
9421
9422 case InferredType::Object:
9423 speculate(BadType, jsValueValue(value), edge.node(), isNotCell(value, provenType(edge)));
9424 speculate(BadType, jsValueValue(value), edge.node(), isNotObject(value, provenType(edge)));
9425 return;
9426
9427 case InferredType::ObjectOrOther: {
fpizlo@apple.com91331742016-03-07 02:07:28 +00009428 LBasicBlock cellCase = m_out.newBlock();
9429 LBasicBlock notCellCase = m_out.newBlock();
9430 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com12835772015-09-21 20:49:04 +00009431
9432 m_out.branch(isCell(value, provenType(edge)), unsure(cellCase), unsure(notCellCase));
9433
9434 LBasicBlock lastNext = m_out.appendTo(cellCase, notCellCase);
9435
9436 speculate(
9437 BadType, jsValueValue(value), edge.node(),
9438 isNotObject(value, provenType(edge) & SpecCell));
9439
9440 m_out.jump(continuation);
9441
9442 m_out.appendTo(notCellCase, continuation);
9443
9444 speculate(
9445 BadType, jsValueValue(value), edge.node(),
9446 isNotOther(value, provenType(edge) & ~SpecCell));
9447
9448 m_out.jump(continuation);
9449
9450 m_out.appendTo(continuation, lastNext);
9451 return;
9452 }
9453
9454 case InferredType::Top:
9455 return;
9456 }
9457
9458 DFG_CRASH(m_graph, m_node, "Bad inferred type");
9459 }
fpizlo@apple.com29594fe2014-03-21 00:32:37 +00009460
fpizlo@apple.com43219522014-02-25 02:02:50 +00009461 LValue loadProperty(LValue storage, unsigned identifierNumber, PropertyOffset offset)
9462 {
9463 return m_out.load64(addressOfProperty(storage, identifierNumber, offset));
9464 }
9465
9466 void storeProperty(
9467 LValue value, LValue storage, unsigned identifierNumber, PropertyOffset offset)
9468 {
9469 m_out.store64(value, addressOfProperty(storage, identifierNumber, offset));
9470 }
9471
9472 TypedPointer addressOfProperty(
9473 LValue storage, unsigned identifierNumber, PropertyOffset offset)
9474 {
9475 return m_out.address(
9476 m_heaps.properties[identifierNumber], storage, offsetRelativeToBase(offset));
9477 }
9478
9479 LValue storageForTransition(
9480 LValue object, PropertyOffset offset,
9481 Structure* previousStructure, Structure* nextStructure)
9482 {
9483 if (isInlineOffset(offset))
9484 return object;
9485
9486 if (previousStructure->outOfLineCapacity() == nextStructure->outOfLineCapacity())
fpizlo@apple.com95ef6492016-03-15 15:26:36 +00009487 return m_out.loadPtr(object, m_heaps.JSObject_butterfly);
fpizlo@apple.com43219522014-02-25 02:02:50 +00009488
9489 LValue result;
9490 if (!previousStructure->outOfLineCapacity())
9491 result = allocatePropertyStorage(object, previousStructure);
9492 else {
9493 result = reallocatePropertyStorage(
fpizlo@apple.com95ef6492016-03-15 15:26:36 +00009494 object, m_out.loadPtr(object, m_heaps.JSObject_butterfly),
fpizlo@apple.com43219522014-02-25 02:02:50 +00009495 previousStructure, nextStructure);
9496 }
9497
fpizlo@apple.comb0e7f3d2016-12-10 01:22:15 +00009498 nukeStructureAndSetButterfly(result, object);
fpizlo@apple.com43219522014-02-25 02:02:50 +00009499 return result;
9500 }
fpizlo@apple.com280ef002016-04-05 22:13:16 +00009501
sbarati@apple.comfd407a52017-01-13 04:03:47 +00009502 void initializeArrayElements(LValue indexingType, LValue begin, LValue end, LValue butterfly)
fpizlo@apple.com280ef002016-04-05 22:13:16 +00009503 {
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00009504
9505 if (begin == end)
9506 return;
9507
sbarati@apple.comfd407a52017-01-13 04:03:47 +00009508 if (indexingType->hasInt32()) {
9509 IndexingType rawIndexingType = static_cast<IndexingType>(indexingType->asInt32());
9510 if (hasUndecided(rawIndexingType))
9511 return;
9512 IndexedAbstractHeap* heap = m_heaps.forIndexingType(rawIndexingType);
9513 DFG_ASSERT(m_graph, m_node, heap);
9514
9515 LValue hole;
9516 if (hasDouble(rawIndexingType))
9517 hole = m_out.constInt64(bitwise_cast<int64_t>(PNaN));
9518 else
9519 hole = m_out.constInt64(JSValue::encode(JSValue()));
9520
9521 splatWords(butterfly, begin, end, hole, heap->atAnyIndex());
9522 } else {
9523 LValue hole = m_out.select(
9524 m_out.equal(m_out.bitAnd(indexingType, m_out.constInt32(IndexingShapeMask)), m_out.constInt32(DoubleShape)),
9525 m_out.constInt64(bitwise_cast<int64_t>(PNaN)),
9526 m_out.constInt64(JSValue::encode(JSValue())));
9527 splatWords(butterfly, begin, end, hole, m_heaps.root);
9528 }
fpizlo@apple.com30a72582016-09-08 16:47:34 +00009529 }
sbarati@apple.comfd407a52017-01-13 04:03:47 +00009530
fpizlo@apple.com30a72582016-09-08 16:47:34 +00009531 void splatWords(LValue base, LValue begin, LValue end, LValue value, const AbstractHeap& heap)
9532 {
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00009533 const uint64_t unrollingLimit = 10;
9534 if (begin->hasInt() && end->hasInt()) {
9535 uint64_t beginConst = static_cast<uint64_t>(begin->asInt());
9536 uint64_t endConst = static_cast<uint64_t>(end->asInt());
9537
9538 if (endConst - beginConst <= unrollingLimit) {
fpizlo@apple.com30a72582016-09-08 16:47:34 +00009539 for (uint64_t i = beginConst; i < endConst; ++i) {
9540 LValue pointer = m_out.add(base, m_out.constIntPtr(i * sizeof(uint64_t)));
9541 m_out.store64(value, TypedPointer(heap, pointer));
9542 }
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00009543 return;
9544 }
fpizlo@apple.com595eebd2016-08-24 19:00:37 +00009545 }
fpizlo@apple.com280ef002016-04-05 22:13:16 +00009546
fpizlo@apple.com280ef002016-04-05 22:13:16 +00009547 LBasicBlock initLoop = m_out.newBlock();
9548 LBasicBlock initDone = m_out.newBlock();
9549
fpizlo@apple.com30a72582016-09-08 16:47:34 +00009550 LBasicBlock lastNext = m_out.insertNewBlocksBefore(initLoop);
9551
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00009552 ValueFromBlock originalIndex = m_out.anchor(end);
fpizlo@apple.com101a1682016-11-15 01:49:22 +00009553 ValueFromBlock originalPointer = m_out.anchor(
9554 m_out.add(base, m_out.shl(m_out.signExt32ToPtr(begin), m_out.constInt32(3))));
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00009555 m_out.branch(m_out.notEqual(end, begin), unsure(initLoop), unsure(initDone));
fpizlo@apple.com280ef002016-04-05 22:13:16 +00009556
fpizlo@apple.com30a72582016-09-08 16:47:34 +00009557 m_out.appendTo(initLoop, initDone);
fpizlo@apple.com994d4532016-07-03 19:34:55 +00009558 LValue index = m_out.phi(Int32, originalIndex);
9559 LValue pointer = m_out.phi(pointerType(), originalPointer);
fpizlo@apple.com280ef002016-04-05 22:13:16 +00009560
fpizlo@apple.com30a72582016-09-08 16:47:34 +00009561 m_out.store64(value, TypedPointer(heap, pointer));
fpizlo@apple.com280ef002016-04-05 22:13:16 +00009562
9563 LValue nextIndex = m_out.sub(index, m_out.int32One);
9564 m_out.addIncomingToPhi(index, m_out.anchor(nextIndex));
9565 m_out.addIncomingToPhi(pointer, m_out.anchor(m_out.add(pointer, m_out.intPtrEight)));
9566 m_out.branch(
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00009567 m_out.notEqual(nextIndex, begin), unsure(initLoop), unsure(initDone));
fpizlo@apple.com280ef002016-04-05 22:13:16 +00009568
fpizlo@apple.com30a72582016-09-08 16:47:34 +00009569 m_out.appendTo(initDone, lastNext);
fpizlo@apple.com280ef002016-04-05 22:13:16 +00009570 }
fpizlo@apple.com43219522014-02-25 02:02:50 +00009571
9572 LValue allocatePropertyStorage(LValue object, Structure* previousStructure)
9573 {
9574 if (previousStructure->couldHaveIndexingHeader()) {
9575 return vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00009576 pointerType(),
fpizlo@apple.comb0e7f3d2016-12-10 01:22:15 +00009577 m_out.operation(operationAllocateComplexPropertyStorageWithInitialCapacity),
fpizlo@apple.com43219522014-02-25 02:02:50 +00009578 m_callFrame, object);
9579 }
9580
fpizlo@apple.comec881de62014-09-22 20:25:49 +00009581 LValue result = allocatePropertyStorageWithSizeImpl(initialOutOfLineCapacity);
fpizlo@apple.com101a1682016-11-15 01:49:22 +00009582
fpizlo@apple.comb09568c2016-12-09 03:30:03 +00009583 splatWords(
9584 result,
9585 m_out.constInt32(-initialOutOfLineCapacity - 1), m_out.constInt32(-1),
9586 m_out.int64Zero, m_heaps.properties.atAnyNumber());
fpizlo@apple.com101a1682016-11-15 01:49:22 +00009587
fpizlo@apple.com43219522014-02-25 02:02:50 +00009588 return result;
9589 }
9590
9591 LValue reallocatePropertyStorage(
9592 LValue object, LValue oldStorage, Structure* previous, Structure* next)
9593 {
fpizlo@apple.comec881de62014-09-22 20:25:49 +00009594 size_t oldSize = previous->outOfLineCapacity();
fpizlo@apple.com43219522014-02-25 02:02:50 +00009595 size_t newSize = oldSize * outOfLineGrowthFactor;
9596
fpizlo@apple.comec881de62014-09-22 20:25:49 +00009597 ASSERT_UNUSED(next, newSize == next->outOfLineCapacity());
fpizlo@apple.com43219522014-02-25 02:02:50 +00009598
9599 if (previous->couldHaveIndexingHeader()) {
fpizlo@apple.comec881de62014-09-22 20:25:49 +00009600 LValue newAllocSize = m_out.constIntPtr(newSize);
fpizlo@apple.comb0e7f3d2016-12-10 01:22:15 +00009601 return vmCall(pointerType(), m_out.operation(operationAllocateComplexPropertyStorage), m_callFrame, object, newAllocSize);
fpizlo@apple.com43219522014-02-25 02:02:50 +00009602 }
9603
fpizlo@apple.comec881de62014-09-22 20:25:49 +00009604 LValue result = allocatePropertyStorageWithSizeImpl(newSize);
fpizlo@apple.com43219522014-02-25 02:02:50 +00009605
fpizlo@apple.comec881de62014-09-22 20:25:49 +00009606 ptrdiff_t headerSize = -sizeof(IndexingHeader) - sizeof(void*);
9607 ptrdiff_t endStorage = headerSize - static_cast<ptrdiff_t>(oldSize * sizeof(JSValue));
fpizlo@apple.com43219522014-02-25 02:02:50 +00009608
9609 for (ptrdiff_t offset = headerSize; offset > endStorage; offset -= sizeof(void*)) {
9610 LValue loaded =
9611 m_out.loadPtr(m_out.address(m_heaps.properties.atAnyNumber(), oldStorage, offset));
9612 m_out.storePtr(loaded, m_out.address(m_heaps.properties.atAnyNumber(), result, offset));
9613 }
9614
fpizlo@apple.comb09568c2016-12-09 03:30:03 +00009615 splatWords(
9616 result,
9617 m_out.constInt32(-newSize - 1), m_out.constInt32(-oldSize - 1),
9618 m_out.int64Zero, m_heaps.properties.atAnyNumber());
fpizlo@apple.com101a1682016-11-15 01:49:22 +00009619
fpizlo@apple.com43219522014-02-25 02:02:50 +00009620 return result;
9621 }
9622
fpizlo@apple.comec881de62014-09-22 20:25:49 +00009623 LValue allocatePropertyStorageWithSizeImpl(size_t sizeInValues)
9624 {
fpizlo@apple.com91331742016-03-07 02:07:28 +00009625 LBasicBlock slowPath = m_out.newBlock();
9626 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.comec881de62014-09-22 20:25:49 +00009627
9628 LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00009629
9630 size_t sizeInBytes = sizeInValues * sizeof(JSValue);
fpizlo@apple.com5fa9d962017-01-18 04:22:45 +00009631 MarkedAllocator* allocator = vm().auxiliarySpace.allocatorFor(sizeInBytes);
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00009632 LValue startOfStorage = allocateHeapCell(m_out.constIntPtr(allocator), slowPath);
fpizlo@apple.comec881de62014-09-22 20:25:49 +00009633 ValueFromBlock fastButterfly = m_out.anchor(
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +00009634 m_out.add(m_out.constIntPtr(sizeInBytes + sizeof(IndexingHeader)), startOfStorage));
fpizlo@apple.comec881de62014-09-22 20:25:49 +00009635 m_out.jump(continuation);
9636
9637 m_out.appendTo(slowPath, continuation);
9638
9639 LValue slowButterflyValue;
9640 if (sizeInValues == initialOutOfLineCapacity) {
fpizlo@apple.com6e697962015-10-12 17:56:26 +00009641 slowButterflyValue = lazySlowPath(
9642 [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
9643 return createLazyCallGenerator(
fpizlo@apple.comb0e7f3d2016-12-10 01:22:15 +00009644 operationAllocateSimplePropertyStorageWithInitialCapacity,
fpizlo@apple.com6e697962015-10-12 17:56:26 +00009645 locations[0].directGPR());
9646 });
fpizlo@apple.comec881de62014-09-22 20:25:49 +00009647 } else {
fpizlo@apple.com6e697962015-10-12 17:56:26 +00009648 slowButterflyValue = lazySlowPath(
9649 [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
9650 return createLazyCallGenerator(
fpizlo@apple.comb0e7f3d2016-12-10 01:22:15 +00009651 operationAllocateSimplePropertyStorage, locations[0].directGPR(),
fpizlo@apple.com6e697962015-10-12 17:56:26 +00009652 CCallHelpers::TrustedImmPtr(sizeInValues));
9653 });
fpizlo@apple.comec881de62014-09-22 20:25:49 +00009654 }
9655 ValueFromBlock slowButterfly = m_out.anchor(slowButterflyValue);
9656
9657 m_out.jump(continuation);
9658
9659 m_out.appendTo(continuation, lastNext);
9660
fpizlo@apple.com994d4532016-07-03 19:34:55 +00009661 return m_out.phi(pointerType(), fastButterfly, slowButterfly);
fpizlo@apple.comec881de62014-09-22 20:25:49 +00009662 }
9663
keith_miller@apple.com7deaba82016-04-10 03:38:44 +00009664 LValue getById(LValue base, AccessType type)
fpizlo@apple.coma14dfc02014-01-30 23:00:16 +00009665 {
fpizlo@apple.com91aea582015-12-10 03:50:07 +00009666 Node* node = m_node;
9667 UniquedStringImpl* uid = m_graph.identifiers()[node->identifierNumber()];
9668
fpizlo@apple.com91aea582015-12-10 03:50:07 +00009669 B3::PatchpointValue* patchpoint = m_out.patchpoint(Int64);
fpizlo@apple.com45e45652016-01-07 21:20:37 +00009670 patchpoint->appendSomeRegister(base);
sbarati@apple.com15af88b2016-05-11 20:54:09 +00009671 patchpoint->append(m_tagMask, ValueRep::lateReg(GPRInfo::tagMaskRegister));
9672 patchpoint->append(m_tagTypeNumber, ValueRep::lateReg(GPRInfo::tagTypeNumberRegister));
fpizlo@apple.com45e45652016-01-07 21:20:37 +00009673
9674 // FIXME: If this is a GetByIdFlush, we might get some performance boost if we claim that it
9675 // clobbers volatile registers late. It's not necessary for correctness, though, since the
9676 // IC code is super smart about saving registers.
9677 // https://bugs.webkit.org/show_bug.cgi?id=152848
9678
fpizlo@apple.com91aea582015-12-10 03:50:07 +00009679 patchpoint->clobber(RegisterSet::macroScratchRegisters());
benjamin@webkit.org81ec96c2015-11-18 23:14:54 +00009680
fpizlo@apple.com45e45652016-01-07 21:20:37 +00009681 RefPtr<PatchpointExceptionHandle> exceptionHandle =
9682 preparePatchpointForExceptions(patchpoint);
9683
fpizlo@apple.com91aea582015-12-10 03:50:07 +00009684 State* state = &m_ftlState;
9685 patchpoint->setGenerator(
9686 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
9687 AllowMacroScratchRegisterUsage allowScratch(jit);
9688
fpizlo@apple.com45e45652016-01-07 21:20:37 +00009689 CallSiteIndex callSiteIndex =
9690 state->jitCode->common.addUniqueCallSiteIndex(node->origin.semantic);
9691
9692 // This is the direct exit target for operation calls.
9693 Box<CCallHelpers::JumpList> exceptions =
9694 exceptionHandle->scheduleExitCreation(params)->jumps(jit);
9695
9696 // This is the exit for call IC's created by the getById for getters. We don't have
9697 // to do anything weird other than call this, since it will associate the exit with
9698 // the callsite index.
9699 exceptionHandle->scheduleExitCreationForUnwind(params, callSiteIndex);
9700
fpizlo@apple.com91aea582015-12-10 03:50:07 +00009701 auto generator = Box<JITGetByIdGenerator>::create(
fpizlo@apple.com45e45652016-01-07 21:20:37 +00009702 jit.codeBlock(), node->origin.semantic, callSiteIndex,
sbarati@apple.comb5bee812016-06-19 19:42:18 +00009703 params.unavailableRegisters(), uid, JSValueRegs(params[1].gpr()),
keith_miller@apple.com7deaba82016-04-10 03:38:44 +00009704 JSValueRegs(params[0].gpr()), type);
fpizlo@apple.com91aea582015-12-10 03:50:07 +00009705
9706 generator->generateFastPath(jit);
9707 CCallHelpers::Label done = jit.label();
9708
9709 params.addLatePath(
9710 [=] (CCallHelpers& jit) {
9711 AllowMacroScratchRegisterUsage allowScratch(jit);
fpizlo@apple.com91aea582015-12-10 03:50:07 +00009712
keith_miller@apple.com7deaba82016-04-10 03:38:44 +00009713 J_JITOperation_ESsiJI optimizationFunction;
9714 if (type == AccessType::Get)
9715 optimizationFunction = operationGetByIdOptimize;
9716 else
9717 optimizationFunction = operationTryGetByIdOptimize;
9718
fpizlo@apple.com91aea582015-12-10 03:50:07 +00009719 generator->slowPathJump().link(&jit);
9720 CCallHelpers::Label slowPathBegin = jit.label();
9721 CCallHelpers::Call slowPathCall = callOperation(
fpizlo@apple.com86cbf132015-12-28 22:46:51 +00009722 *state, params.unavailableRegisters(), jit, node->origin.semantic,
keith_miller@apple.com7deaba82016-04-10 03:38:44 +00009723 exceptions.get(), optimizationFunction, params[0].gpr(),
fpizlo@apple.com91aea582015-12-10 03:50:07 +00009724 CCallHelpers::TrustedImmPtr(generator->stubInfo()), params[1].gpr(),
9725 CCallHelpers::TrustedImmPtr(uid)).call();
9726 jit.jump().linkTo(done, &jit);
9727
9728 generator->reportSlowPathCall(slowPathBegin, slowPathCall);
9729
9730 jit.addLinkTask(
9731 [=] (LinkBuffer& linkBuffer) {
9732 generator->finalize(linkBuffer);
9733 });
9734 });
9735 });
9736
9737 return patchpoint;
fpizlo@apple.coma14dfc02014-01-30 23:00:16 +00009738 }
fpizlo@apple.com8dde06b2015-10-12 22:41:01 +00009739
fpizlo@apple.com1e158382015-10-16 22:53:11 +00009740 LValue isFastTypedArray(LValue object)
9741 {
9742 return m_out.equal(
9743 m_out.load32(object, m_heaps.JSArrayBufferView_mode),
9744 m_out.constInt32(FastTypedArray));
9745 }
fpizlo@apple.coma14dfc02014-01-30 23:00:16 +00009746
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00009747 TypedPointer baseIndex(IndexedAbstractHeap& heap, LValue storage, LValue index, Edge edge, ptrdiff_t offset = 0)
fpizlo@apple.com5dba3f12013-12-06 22:05:10 +00009748 {
9749 return m_out.baseIndex(
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +00009750 heap, storage, m_out.zeroExtPtr(index), provenValue(edge), offset);
fpizlo@apple.com5dba3f12013-12-06 22:05:10 +00009751 }
fpizlo@apple.com12a3fbd2015-11-19 22:18:15 +00009752
9753 template<typename IntFunctor, typename DoubleFunctor>
fpizlo@apple.com929434a2013-12-09 01:06:54 +00009754 void compare(
fpizlo@apple.com12a3fbd2015-11-19 22:18:15 +00009755 const IntFunctor& intFunctor, const DoubleFunctor& doubleFunctor,
commit-queue@webkit.org36c52882016-04-22 05:08:28 +00009756 C_JITOperation_TT stringIdentFunction,
9757 C_JITOperation_B_EJssJss stringFunction,
9758 S_JITOperation_EJJ fallbackFunction)
fpizlo@apple.com929434a2013-12-09 01:06:54 +00009759 {
9760 if (m_node->isBinaryUseKind(Int32Use)) {
9761 LValue left = lowInt32(m_node->child1());
9762 LValue right = lowInt32(m_node->child2());
fpizlo@apple.com12a3fbd2015-11-19 22:18:15 +00009763 setBoolean(intFunctor(left, right));
fpizlo@apple.com929434a2013-12-09 01:06:54 +00009764 return;
9765 }
9766
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00009767 if (m_node->isBinaryUseKind(Int52RepUse)) {
fpizlo@apple.com929434a2013-12-09 01:06:54 +00009768 Int52Kind kind;
9769 LValue left = lowWhicheverInt52(m_node->child1(), kind);
9770 LValue right = lowInt52(m_node->child2(), kind);
fpizlo@apple.com12a3fbd2015-11-19 22:18:15 +00009771 setBoolean(intFunctor(left, right));
fpizlo@apple.com929434a2013-12-09 01:06:54 +00009772 return;
9773 }
9774
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +00009775 if (m_node->isBinaryUseKind(DoubleRepUse)) {
fpizlo@apple.com929434a2013-12-09 01:06:54 +00009776 LValue left = lowDouble(m_node->child1());
9777 LValue right = lowDouble(m_node->child2());
fpizlo@apple.com12a3fbd2015-11-19 22:18:15 +00009778 setBoolean(doubleFunctor(left, right));
fpizlo@apple.com929434a2013-12-09 01:06:54 +00009779 return;
9780 }
commit-queue@webkit.org36c52882016-04-22 05:08:28 +00009781
9782 if (m_node->isBinaryUseKind(StringIdentUse)) {
9783 LValue left = lowStringIdent(m_node->child1());
9784 LValue right = lowStringIdent(m_node->child2());
fpizlo@apple.com994d4532016-07-03 19:34:55 +00009785 setBoolean(m_out.callWithoutSideEffects(Int32, stringIdentFunction, left, right));
commit-queue@webkit.org36c52882016-04-22 05:08:28 +00009786 return;
9787 }
9788
9789 if (m_node->isBinaryUseKind(StringUse)) {
9790 LValue left = lowCell(m_node->child1());
9791 LValue right = lowCell(m_node->child2());
9792 speculateString(m_node->child1(), left);
9793 speculateString(m_node->child2(), right);
9794
9795 LValue result = vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +00009796 Int32, m_out.operation(stringFunction),
commit-queue@webkit.org36c52882016-04-22 05:08:28 +00009797 m_callFrame, left, right);
9798 setBoolean(result);
9799 return;
9800 }
9801
commit-queue@webkit.orgdd1f8702016-08-30 22:43:12 +00009802 DFG_ASSERT(m_graph, m_node, m_node->isBinaryUseKind(UntypedUse));
9803 nonSpeculativeCompare(intFunctor, fallbackFunction);
fpizlo@apple.com929434a2013-12-09 01:06:54 +00009804 }
sbarati@apple.come67fd782016-04-19 01:38:30 +00009805
sbarati@apple.com527ebc22016-10-05 06:16:15 +00009806 void compileToLowerCase()
9807 {
9808 LBasicBlock notRope = m_out.newBlock();
9809 LBasicBlock is8Bit = m_out.newBlock();
9810 LBasicBlock loopTop = m_out.newBlock();
9811 LBasicBlock loopBody = m_out.newBlock();
9812 LBasicBlock slowPath = m_out.newBlock();
9813 LBasicBlock continuation = m_out.newBlock();
9814
9815 LValue string = lowString(m_node->child1());
9816 ValueFromBlock startIndex = m_out.anchor(m_out.constInt32(0));
9817 ValueFromBlock startIndexForCall = m_out.anchor(m_out.constInt32(0));
9818 LValue impl = m_out.loadPtr(string, m_heaps.JSString_value);
9819 m_out.branch(m_out.isZero64(impl),
9820 unsure(slowPath), unsure(notRope));
9821
9822 LBasicBlock lastNext = m_out.appendTo(notRope, is8Bit);
9823
9824 m_out.branch(
9825 m_out.testIsZero32(
9826 m_out.load32(impl, m_heaps.StringImpl_hashAndFlags),
9827 m_out.constInt32(StringImpl::flagIs8Bit())),
9828 unsure(slowPath), unsure(is8Bit));
9829
9830 m_out.appendTo(is8Bit, loopTop);
9831 LValue length = m_out.load32(impl, m_heaps.StringImpl_length);
9832 LValue buffer = m_out.loadPtr(impl, m_heaps.StringImpl_data);
9833 ValueFromBlock fastResult = m_out.anchor(string);
9834 m_out.jump(loopTop);
9835
9836 m_out.appendTo(loopTop, loopBody);
9837 LValue index = m_out.phi(Int32, startIndex);
9838 ValueFromBlock indexFromBlock = m_out.anchor(index);
9839 m_out.branch(m_out.below(index, length),
9840 unsure(loopBody), unsure(continuation));
9841
9842 m_out.appendTo(loopBody, slowPath);
9843
9844 LValue byte = m_out.load8ZeroExt32(m_out.baseIndex(m_heaps.characters8, buffer, m_out.zeroExtPtr(index)));
9845 LValue isInvalidAsciiRange = m_out.bitAnd(byte, m_out.constInt32(~0x7F));
9846 LValue isUpperCase = m_out.belowOrEqual(m_out.sub(byte, m_out.constInt32('A')), m_out.constInt32('Z' - 'A'));
9847 LValue isBadCharacter = m_out.bitOr(isInvalidAsciiRange, isUpperCase);
9848 m_out.addIncomingToPhi(index, m_out.anchor(m_out.add(index, m_out.int32One)));
9849 m_out.branch(isBadCharacter, unsure(slowPath), unsure(loopTop));
9850
9851 m_out.appendTo(slowPath, continuation);
9852 LValue slowPathIndex = m_out.phi(Int32, startIndexForCall, indexFromBlock);
9853 ValueFromBlock slowResult = m_out.anchor(vmCall(pointerType(), m_out.operation(operationToLowerCase), m_callFrame, string, slowPathIndex));
9854 m_out.jump(continuation);
9855
9856 m_out.appendTo(continuation, lastNext);
9857 setJSValue(m_out.phi(pointerType(), fastResult, slowResult));
9858 }
9859
sbarati@apple.come67fd782016-04-19 01:38:30 +00009860 void compileResolveScope()
9861 {
9862 UniquedStringImpl* uid = m_graph.identifiers()[m_node->identifierNumber()];
fpizlo@apple.com994d4532016-07-03 19:34:55 +00009863 setJSValue(vmCall(pointerType(), m_out.operation(operationResolveScope),
sbarati@apple.come67fd782016-04-19 01:38:30 +00009864 m_callFrame, lowCell(m_node->child1()), m_out.constIntPtr(uid)));
9865 }
9866
9867 void compileGetDynamicVar()
9868 {
9869 UniquedStringImpl* uid = m_graph.identifiers()[m_node->identifierNumber()];
fpizlo@apple.com994d4532016-07-03 19:34:55 +00009870 setJSValue(vmCall(Int64, m_out.operation(operationGetDynamicVar),
sbarati@apple.come67fd782016-04-19 01:38:30 +00009871 m_callFrame, lowCell(m_node->child1()), m_out.constIntPtr(uid), m_out.constInt32(m_node->getPutInfo())));
9872 }
9873
9874 void compilePutDynamicVar()
9875 {
9876 UniquedStringImpl* uid = m_graph.identifiers()[m_node->identifierNumber()];
9877 setJSValue(vmCall(Void, m_out.operation(operationPutDynamicVar),
9878 m_callFrame, lowCell(m_node->child1()), lowJSValue(m_node->child2()), m_out.constIntPtr(uid), m_out.constInt32(m_node->getPutInfo())));
9879 }
fpizlo@apple.com929434a2013-12-09 01:06:54 +00009880
fpizlo@apple.comadbf11d2016-06-10 19:56:18 +00009881 void compileUnreachable()
9882 {
9883 // It's so tempting to assert that AI has proved that this is unreachable. But that's
9884 // simply not a requirement of the Unreachable opcode at all. If you emit an opcode that
9885 // *you* know will not return, then it's fine to end the basic block with Unreachable
9886 // after that opcode. You don't have to also prove to AI that your opcode does not return.
9887 // Hence, there is nothing to do here but emit code that will crash, so that we catch
9888 // cases where you said Unreachable but you lied.
9889
9890 crash();
9891 }
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +00009892
9893 void compileCheckDOM()
9894 {
9895 LValue cell = lowCell(m_node->child1());
9896
utatane.tea@gmail.com48b9cac2016-10-12 20:47:51 +00009897 DOMJIT::Patchpoint* domJIT = m_node->checkDOMPatchpoint();
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +00009898
9899 PatchpointValue* patchpoint = m_out.patchpoint(Void);
9900 patchpoint->appendSomeRegister(cell);
utatane.tea@gmail.combef79f82016-10-10 19:57:55 +00009901 patchpoint->append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister));
9902 patchpoint->append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister));
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +00009903
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +00009904 NodeOrigin origin = m_origin;
9905 unsigned osrExitArgumentOffset = patchpoint->numChildren();
9906 OSRExitDescriptor* exitDescriptor = appendOSRExitDescriptor(jsValueValue(cell), m_node->child1().node());
9907 patchpoint->appendColdAnys(buildExitArguments(exitDescriptor, origin.forExit, jsValueValue(cell)));
utatane.tea@gmail.comb8bcf662016-11-15 19:21:41 +00009908
9909 patchpoint->numGPScratchRegisters = domJIT->numGPScratchRegisters;
9910 patchpoint->numFPScratchRegisters = domJIT->numFPScratchRegisters;
9911 patchpoint->clobber(RegisterSet::macroScratchRegisters());
9912
9913 State* state = &m_ftlState;
9914 Node* node = m_node;
utatane.tea@gmail.coma2b352a2016-10-11 21:33:11 +00009915 JSValue child1Constant = m_state.forNode(m_node->child1()).value();
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +00009916
9917 patchpoint->setGenerator(
9918 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
utatane.tea@gmail.comb8bcf662016-11-15 19:21:41 +00009919 AllowMacroScratchRegisterUsage allowScratch(jit);
9920
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +00009921 Vector<GPRReg> gpScratch;
9922 Vector<FPRReg> fpScratch;
utatane.tea@gmail.coma2b352a2016-10-11 21:33:11 +00009923 Vector<DOMJIT::Value> regs;
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +00009924
utatane.tea@gmail.coma2b352a2016-10-11 21:33:11 +00009925 regs.append(DOMJIT::Value(params[0].gpr(), child1Constant));
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +00009926
9927 for (unsigned i = 0; i < domJIT->numGPScratchRegisters; ++i)
9928 gpScratch.append(params.gpScratch(i));
9929
9930 for (unsigned i = 0; i < domJIT->numFPScratchRegisters; ++i)
9931 fpScratch.append(params.fpScratch(i));
9932
9933 RefPtr<OSRExitHandle> handle = exitDescriptor->emitOSRExitLater(*state, BadType, origin, params, osrExitArgumentOffset);
9934
utatane.tea@gmail.comad4eb052016-10-07 05:07:13 +00009935 DOMJITPatchpointParams domJITParams(*state, params, node, nullptr, WTFMove(regs), WTFMove(gpScratch), WTFMove(fpScratch));
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +00009936 CCallHelpers::JumpList failureCases = domJIT->generator()->run(jit, domJITParams);
9937
9938 jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
9939 linkBuffer.link(failureCases, linkBuffer.locationOf(handle->label));
9940 });
9941 });
9942 patchpoint->effects = Effects::forCheck();
9943 }
9944
utatane.tea@gmail.com0d74c7c2016-11-03 03:20:53 +00009945 void compileCallDOM()
9946 {
9947 const DOMJIT::Signature* signature = m_node->signature();
9948
9949 // FIXME: We should have a way to call functions with the vector of registers.
9950 // https://bugs.webkit.org/show_bug.cgi?id=163099
9951 Vector<LValue, JSC_DOMJIT_SIGNATURE_MAX_ARGUMENTS_INCLUDING_THIS> operands;
9952
9953 unsigned index = 0;
9954 DFG_NODE_DO_TO_CHILDREN(m_graph, m_node, [&](Node*, Edge edge) {
9955 if (!index)
9956 operands.append(lowCell(edge));
9957 else {
9958 switch (signature->arguments[index - 1]) {
9959 case SpecString:
9960 operands.append(lowString(edge));
9961 break;
9962 case SpecInt32Only:
9963 operands.append(lowInt32(edge));
9964 break;
9965 case SpecBoolean:
9966 operands.append(lowBoolean(edge));
9967 break;
9968 default:
9969 RELEASE_ASSERT_NOT_REACHED();
9970 break;
9971 }
9972 }
9973 ++index;
9974 });
9975
9976 unsigned argumentCountIncludingThis = signature->argumentCount + 1;
9977 LValue result;
9978 switch (argumentCountIncludingThis) {
9979 case 1:
9980 result = vmCall(Int64, m_out.operation(reinterpret_cast<J_JITOperation_EP>(signature->unsafeFunction)), m_callFrame, operands[0]);
9981 break;
9982 case 2:
9983 result = vmCall(Int64, m_out.operation(reinterpret_cast<J_JITOperation_EPP>(signature->unsafeFunction)), m_callFrame, operands[0], operands[1]);
9984 break;
9985 case 3:
9986 result = vmCall(Int64, m_out.operation(reinterpret_cast<J_JITOperation_EPPP>(signature->unsafeFunction)), m_callFrame, operands[0], operands[1], operands[2]);
9987 break;
9988 default:
9989 RELEASE_ASSERT_NOT_REACHED();
9990 break;
9991 }
9992
9993 setJSValue(result);
9994 }
9995
utatane.tea@gmail.comc9d8f862016-10-28 22:57:10 +00009996 void compileCallDOMGetter()
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +00009997 {
utatane.tea@gmail.comc9d8f862016-10-28 22:57:10 +00009998 DOMJIT::CallDOMGetterPatchpoint* domJIT = m_node->callDOMGetterData()->patchpoint;
utatane.tea@gmail.com90399a22016-10-24 23:34:32 +00009999
10000 Edge& baseEdge = m_node->child1();
10001 LValue base = lowCell(baseEdge);
10002 JSValue baseConstant = m_state.forNode(baseEdge).value();
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +000010003
utatane.tea@gmail.com48b9cac2016-10-12 20:47:51 +000010004 LValue globalObject;
10005 JSValue globalObjectConstant;
10006 if (domJIT->requireGlobalObject) {
utatane.tea@gmail.com90399a22016-10-24 23:34:32 +000010007 Edge& globalObjectEdge = m_node->child2();
utatane.tea@gmail.com48b9cac2016-10-12 20:47:51 +000010008 globalObject = lowCell(globalObjectEdge);
10009 globalObjectConstant = m_state.forNode(globalObjectEdge).value();
10010 }
10011
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +000010012 PatchpointValue* patchpoint = m_out.patchpoint(Int64);
utatane.tea@gmail.com90399a22016-10-24 23:34:32 +000010013 patchpoint->appendSomeRegister(base);
utatane.tea@gmail.com48b9cac2016-10-12 20:47:51 +000010014 if (domJIT->requireGlobalObject)
10015 patchpoint->appendSomeRegister(globalObject);
utatane.tea@gmail.combef79f82016-10-10 19:57:55 +000010016 patchpoint->append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister));
10017 patchpoint->append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister));
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +000010018 RefPtr<PatchpointExceptionHandle> exceptionHandle = preparePatchpointForExceptions(patchpoint);
10019 patchpoint->clobber(RegisterSet::macroScratchRegisters());
10020 patchpoint->numGPScratchRegisters = domJIT->numGPScratchRegisters;
10021 patchpoint->numFPScratchRegisters = domJIT->numFPScratchRegisters;
utatane.tea@gmail.combef79f82016-10-10 19:57:55 +000010022 patchpoint->resultConstraint = ValueRep::SomeEarlyRegister;
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +000010023
utatane.tea@gmail.comad4eb052016-10-07 05:07:13 +000010024 State* state = &m_ftlState;
10025 Node* node = m_node;
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +000010026 patchpoint->setGenerator(
10027 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
utatane.tea@gmail.combef79f82016-10-10 19:57:55 +000010028 AllowMacroScratchRegisterUsage allowScratch(jit);
10029
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +000010030 Vector<GPRReg> gpScratch;
10031 Vector<FPRReg> fpScratch;
utatane.tea@gmail.coma2b352a2016-10-11 21:33:11 +000010032 Vector<DOMJIT::Value> regs;
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +000010033
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +000010034 regs.append(JSValueRegs(params[0].gpr()));
utatane.tea@gmail.com90399a22016-10-24 23:34:32 +000010035 regs.append(DOMJIT::Value(params[1].gpr(), baseConstant));
utatane.tea@gmail.com48b9cac2016-10-12 20:47:51 +000010036 if (domJIT->requireGlobalObject)
utatane.tea@gmail.com90399a22016-10-24 23:34:32 +000010037 regs.append(DOMJIT::Value(params[2].gpr(), globalObjectConstant));
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +000010038
10039 for (unsigned i = 0; i < domJIT->numGPScratchRegisters; ++i)
10040 gpScratch.append(params.gpScratch(i));
10041
10042 for (unsigned i = 0; i < domJIT->numFPScratchRegisters; ++i)
10043 fpScratch.append(params.fpScratch(i));
10044
10045 Box<CCallHelpers::JumpList> exceptions = exceptionHandle->scheduleExitCreation(params)->jumps(jit);
10046
utatane.tea@gmail.comad4eb052016-10-07 05:07:13 +000010047 DOMJITPatchpointParams domJITParams(*state, params, node, exceptions, WTFMove(regs), WTFMove(gpScratch), WTFMove(fpScratch));
utatane.tea@gmail.com23a42472016-10-06 05:20:10 +000010048 domJIT->generator()->run(jit, domJITParams);
10049 });
10050 patchpoint->effects = Effects::forCall();
10051 setJSValue(patchpoint);
10052 }
fpizlo@apple.comadbf11d2016-06-10 19:56:18 +000010053
fpizlo@apple.com76e5b2792014-02-11 20:28:59 +000010054 void compareEqObjectOrOtherToObject(Edge leftChild, Edge rightChild)
10055 {
10056 LValue rightCell = lowCell(rightChild);
fpizlo@apple.coma6288692014-02-12 04:13:48 +000010057 LValue leftValue = lowJSValue(leftChild, ManualOperandSpeculation);
fpizlo@apple.com76e5b2792014-02-11 20:28:59 +000010058
10059 speculateTruthyObject(rightChild, rightCell, SpecObject);
10060
fpizlo@apple.com91331742016-03-07 02:07:28 +000010061 LBasicBlock leftCellCase = m_out.newBlock();
10062 LBasicBlock leftNotCellCase = m_out.newBlock();
10063 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com76e5b2792014-02-11 20:28:59 +000010064
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000010065 m_out.branch(
10066 isCell(leftValue, provenType(leftChild)),
10067 unsure(leftCellCase), unsure(leftNotCellCase));
fpizlo@apple.com76e5b2792014-02-11 20:28:59 +000010068
10069 LBasicBlock lastNext = m_out.appendTo(leftCellCase, leftNotCellCase);
10070 speculateTruthyObject(leftChild, leftValue, SpecObject | (~SpecCell));
10071 ValueFromBlock cellResult = m_out.anchor(m_out.equal(rightCell, leftValue));
10072 m_out.jump(continuation);
10073
10074 m_out.appendTo(leftNotCellCase, continuation);
10075 FTL_TYPE_CHECK(
fpizlo@apple.com312efcd2014-03-10 22:11:35 +000010076 jsValueValue(leftValue), leftChild, SpecOther | SpecCell, isNotOther(leftValue));
fpizlo@apple.com76e5b2792014-02-11 20:28:59 +000010077 ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse);
10078 m_out.jump(continuation);
10079
10080 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +000010081 setBoolean(m_out.phi(Int32, cellResult, notCellResult));
fpizlo@apple.com76e5b2792014-02-11 20:28:59 +000010082 }
10083
10084 void speculateTruthyObject(Edge edge, LValue cell, SpeculatedType filter)
10085 {
10086 if (masqueradesAsUndefinedWatchpointIsStillValid()) {
10087 FTL_TYPE_CHECK(jsValueValue(cell), edge, filter, isNotObject(cell));
10088 return;
10089 }
10090
utatane.tea@gmail.com0bfb74c2015-02-24 23:01:58 +000010091 FTL_TYPE_CHECK(jsValueValue(cell), edge, filter, isNotObject(cell));
fpizlo@apple.com76e5b2792014-02-11 20:28:59 +000010092 speculate(
10093 BadType, jsValueValue(cell), edge.node(),
benjamin@webkit.org2e864d22015-11-17 06:20:21 +000010094 m_out.testNonZero32(
10095 m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoFlags),
10096 m_out.constInt32(MasqueradesAsUndefined)));
fpizlo@apple.com76e5b2792014-02-11 20:28:59 +000010097 }
fpizlo@apple.com12a3fbd2015-11-19 22:18:15 +000010098
10099 template<typename IntFunctor>
10100 void nonSpeculativeCompare(const IntFunctor& intFunctor, S_JITOperation_EJJ helperFunction)
fpizlo@apple.com929434a2013-12-09 01:06:54 +000010101 {
10102 LValue left = lowJSValue(m_node->child1());
10103 LValue right = lowJSValue(m_node->child2());
10104
fpizlo@apple.com91331742016-03-07 02:07:28 +000010105 LBasicBlock leftIsInt = m_out.newBlock();
10106 LBasicBlock fastPath = m_out.newBlock();
10107 LBasicBlock slowPath = m_out.newBlock();
10108 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com929434a2013-12-09 01:06:54 +000010109
benjamin@webkit.org977a05b2016-08-27 00:36:15 +000010110 m_out.branch(isNotInt32(left, provenType(m_node->child1())), rarely(slowPath), usually(leftIsInt));
fpizlo@apple.com929434a2013-12-09 01:06:54 +000010111
10112 LBasicBlock lastNext = m_out.appendTo(leftIsInt, fastPath);
benjamin@webkit.org977a05b2016-08-27 00:36:15 +000010113 m_out.branch(isNotInt32(right, provenType(m_node->child2())), rarely(slowPath), usually(fastPath));
fpizlo@apple.com929434a2013-12-09 01:06:54 +000010114
10115 m_out.appendTo(fastPath, slowPath);
fpizlo@apple.com12a3fbd2015-11-19 22:18:15 +000010116 ValueFromBlock fastResult = m_out.anchor(intFunctor(unboxInt32(left), unboxInt32(right)));
fpizlo@apple.com929434a2013-12-09 01:06:54 +000010117 m_out.jump(continuation);
10118
10119 m_out.appendTo(slowPath, continuation);
10120 ValueFromBlock slowResult = m_out.anchor(m_out.notNull(vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +000010121 pointerType(), m_out.operation(helperFunction), m_callFrame, left, right)));
fpizlo@apple.com929434a2013-12-09 01:06:54 +000010122 m_out.jump(continuation);
10123
10124 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +000010125 setBoolean(m_out.phi(Int32, fastResult, slowResult));
fpizlo@apple.com929434a2013-12-09 01:06:54 +000010126 }
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +000010127
fpizlo@apple.com2d17ae02016-02-17 05:29:34 +000010128 LValue stringsEqual(LValue leftJSString, LValue rightJSString)
10129 {
fpizlo@apple.com91331742016-03-07 02:07:28 +000010130 LBasicBlock notTriviallyUnequalCase = m_out.newBlock();
10131 LBasicBlock notEmptyCase = m_out.newBlock();
10132 LBasicBlock leftReadyCase = m_out.newBlock();
10133 LBasicBlock rightReadyCase = m_out.newBlock();
10134 LBasicBlock left8BitCase = m_out.newBlock();
10135 LBasicBlock right8BitCase = m_out.newBlock();
10136 LBasicBlock loop = m_out.newBlock();
10137 LBasicBlock bytesEqual = m_out.newBlock();
10138 LBasicBlock trueCase = m_out.newBlock();
10139 LBasicBlock falseCase = m_out.newBlock();
10140 LBasicBlock slowCase = m_out.newBlock();
10141 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com2d17ae02016-02-17 05:29:34 +000010142
10143 LValue length = m_out.load32(leftJSString, m_heaps.JSString_length);
10144
10145 m_out.branch(
10146 m_out.notEqual(length, m_out.load32(rightJSString, m_heaps.JSString_length)),
10147 unsure(falseCase), unsure(notTriviallyUnequalCase));
10148
10149 LBasicBlock lastNext = m_out.appendTo(notTriviallyUnequalCase, notEmptyCase);
10150
10151 m_out.branch(m_out.isZero32(length), unsure(trueCase), unsure(notEmptyCase));
10152
10153 m_out.appendTo(notEmptyCase, leftReadyCase);
10154
10155 LValue left = m_out.loadPtr(leftJSString, m_heaps.JSString_value);
10156 LValue right = m_out.loadPtr(rightJSString, m_heaps.JSString_value);
10157
10158 m_out.branch(m_out.notNull(left), usually(leftReadyCase), rarely(slowCase));
10159
10160 m_out.appendTo(leftReadyCase, rightReadyCase);
10161
10162 m_out.branch(m_out.notNull(right), usually(rightReadyCase), rarely(slowCase));
10163
10164 m_out.appendTo(rightReadyCase, left8BitCase);
10165
10166 m_out.branch(
10167 m_out.testIsZero32(
10168 m_out.load32(left, m_heaps.StringImpl_hashAndFlags),
10169 m_out.constInt32(StringImpl::flagIs8Bit())),
10170 unsure(slowCase), unsure(left8BitCase));
10171
10172 m_out.appendTo(left8BitCase, right8BitCase);
10173
10174 m_out.branch(
10175 m_out.testIsZero32(
10176 m_out.load32(right, m_heaps.StringImpl_hashAndFlags),
10177 m_out.constInt32(StringImpl::flagIs8Bit())),
10178 unsure(slowCase), unsure(right8BitCase));
10179
10180 m_out.appendTo(right8BitCase, loop);
10181
10182 LValue leftData = m_out.loadPtr(left, m_heaps.StringImpl_data);
10183 LValue rightData = m_out.loadPtr(right, m_heaps.StringImpl_data);
10184
10185 ValueFromBlock indexAtStart = m_out.anchor(length);
10186
10187 m_out.jump(loop);
10188
10189 m_out.appendTo(loop, bytesEqual);
10190
fpizlo@apple.com994d4532016-07-03 19:34:55 +000010191 LValue indexAtLoopTop = m_out.phi(Int32, indexAtStart);
fpizlo@apple.com2d17ae02016-02-17 05:29:34 +000010192 LValue indexInLoop = m_out.sub(indexAtLoopTop, m_out.int32One);
10193
10194 LValue leftByte = m_out.load8ZeroExt32(
10195 m_out.baseIndex(m_heaps.characters8, leftData, m_out.zeroExtPtr(indexInLoop)));
10196 LValue rightByte = m_out.load8ZeroExt32(
10197 m_out.baseIndex(m_heaps.characters8, rightData, m_out.zeroExtPtr(indexInLoop)));
10198
10199 m_out.branch(m_out.notEqual(leftByte, rightByte), unsure(falseCase), unsure(bytesEqual));
10200
10201 m_out.appendTo(bytesEqual, trueCase);
10202
10203 ValueFromBlock indexForNextIteration = m_out.anchor(indexInLoop);
10204 m_out.addIncomingToPhi(indexAtLoopTop, indexForNextIteration);
10205 m_out.branch(m_out.notZero32(indexInLoop), unsure(loop), unsure(trueCase));
10206
10207 m_out.appendTo(trueCase, falseCase);
10208
10209 ValueFromBlock trueResult = m_out.anchor(m_out.booleanTrue);
10210 m_out.jump(continuation);
10211
10212 m_out.appendTo(falseCase, slowCase);
10213
10214 ValueFromBlock falseResult = m_out.anchor(m_out.booleanFalse);
10215 m_out.jump(continuation);
10216
10217 m_out.appendTo(slowCase, continuation);
10218
10219 LValue slowResultValue = vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +000010220 Int64, m_out.operation(operationCompareStringEq), m_callFrame,
fpizlo@apple.com2d17ae02016-02-17 05:29:34 +000010221 leftJSString, rightJSString);
10222 ValueFromBlock slowResult = m_out.anchor(unboxBoolean(slowResultValue));
10223 m_out.jump(continuation);
10224
10225 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +000010226 return m_out.phi(Int32, trueResult, falseResult, slowResult);
fpizlo@apple.com2d17ae02016-02-17 05:29:34 +000010227 }
10228
fpizlo@apple.comb19cd822016-01-04 20:49:33 +000010229 enum ScratchFPRUsage {
10230 DontNeedScratchFPR,
10231 NeedScratchFPR
10232 };
10233 template<typename BinaryArithOpGenerator, ScratchFPRUsage scratchFPRUsage = DontNeedScratchFPR>
10234 void emitBinarySnippet(J_JITOperation_EJJ slowPathFunction)
10235 {
10236 Node* node = m_node;
10237
fpizlo@apple.comb19cd822016-01-04 20:49:33 +000010238 LValue left = lowJSValue(node->child1());
10239 LValue right = lowJSValue(node->child2());
10240
10241 SnippetOperand leftOperand(m_state.forNode(node->child1()).resultType());
10242 SnippetOperand rightOperand(m_state.forNode(node->child2()).resultType());
10243
10244 PatchpointValue* patchpoint = m_out.patchpoint(Int64);
fpizlo@apple.com45e45652016-01-07 21:20:37 +000010245 patchpoint->appendSomeRegister(left);
10246 patchpoint->appendSomeRegister(right);
sbarati@apple.com15af88b2016-05-11 20:54:09 +000010247 patchpoint->append(m_tagMask, ValueRep::lateReg(GPRInfo::tagMaskRegister));
10248 patchpoint->append(m_tagTypeNumber, ValueRep::lateReg(GPRInfo::tagTypeNumberRegister));
fpizlo@apple.comac56fba2016-01-08 01:10:15 +000010249 RefPtr<PatchpointExceptionHandle> exceptionHandle =
10250 preparePatchpointForExceptions(patchpoint);
fpizlo@apple.comb19cd822016-01-04 20:49:33 +000010251 patchpoint->numGPScratchRegisters = 1;
10252 patchpoint->numFPScratchRegisters = 2;
10253 if (scratchFPRUsage == NeedScratchFPR)
10254 patchpoint->numFPScratchRegisters++;
10255 patchpoint->clobber(RegisterSet::macroScratchRegisters());
fpizlo@apple.com8cf609a2016-07-21 05:24:54 +000010256 patchpoint->resultConstraint = ValueRep::SomeEarlyRegister;
fpizlo@apple.comb19cd822016-01-04 20:49:33 +000010257 State* state = &m_ftlState;
10258 patchpoint->setGenerator(
10259 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
10260 AllowMacroScratchRegisterUsage allowScratch(jit);
fpizlo@apple.comac56fba2016-01-08 01:10:15 +000010261
10262 Box<CCallHelpers::JumpList> exceptions =
10263 exceptionHandle->scheduleExitCreation(params)->jumps(jit);
fpizlo@apple.com3511cce2016-01-08 19:02:53 +000010264
fpizlo@apple.comb19cd822016-01-04 20:49:33 +000010265 auto generator = Box<BinaryArithOpGenerator>::create(
10266 leftOperand, rightOperand, JSValueRegs(params[0].gpr()),
10267 JSValueRegs(params[1].gpr()), JSValueRegs(params[2].gpr()),
10268 params.fpScratch(0), params.fpScratch(1), params.gpScratch(0),
10269 scratchFPRUsage == NeedScratchFPR ? params.fpScratch(2) : InvalidFPRReg);
10270
10271 generator->generateFastPath(jit);
fpizlo@apple.comb19cd822016-01-04 20:49:33 +000010272
fpizlo@apple.com3511cce2016-01-08 19:02:53 +000010273 if (generator->didEmitFastPath()) {
10274 generator->endJumpList().link(&jit);
10275 CCallHelpers::Label done = jit.label();
10276
10277 params.addLatePath(
10278 [=] (CCallHelpers& jit) {
10279 AllowMacroScratchRegisterUsage allowScratch(jit);
fpizlo@apple.comb19cd822016-01-04 20:49:33 +000010280
fpizlo@apple.com3511cce2016-01-08 19:02:53 +000010281 generator->slowPathJumpList().link(&jit);
10282 callOperation(
10283 *state, params.unavailableRegisters(), jit, node->origin.semantic,
10284 exceptions.get(), slowPathFunction, params[0].gpr(),
10285 params[1].gpr(), params[2].gpr());
10286 jit.jump().linkTo(done, &jit);
10287 });
10288 } else {
10289 callOperation(
10290 *state, params.unavailableRegisters(), jit, node->origin.semantic,
10291 exceptions.get(), slowPathFunction, params[0].gpr(), params[1].gpr(),
10292 params[2].gpr());
10293 }
fpizlo@apple.comb19cd822016-01-04 20:49:33 +000010294 });
10295
10296 setJSValue(patchpoint);
10297 }
fpizlo@apple.comfee31e22016-01-04 22:31:45 +000010298
10299 template<typename BinaryBitOpGenerator>
10300 void emitBinaryBitOpSnippet(J_JITOperation_EJJ slowPathFunction)
10301 {
10302 Node* node = m_node;
10303
fpizlo@apple.comfee31e22016-01-04 22:31:45 +000010304 LValue left = lowJSValue(node->child1());
10305 LValue right = lowJSValue(node->child2());
10306
10307 SnippetOperand leftOperand(m_state.forNode(node->child1()).resultType());
10308 SnippetOperand rightOperand(m_state.forNode(node->child2()).resultType());
10309
10310 PatchpointValue* patchpoint = m_out.patchpoint(Int64);
fpizlo@apple.com45e45652016-01-07 21:20:37 +000010311 patchpoint->appendSomeRegister(left);
10312 patchpoint->appendSomeRegister(right);
sbarati@apple.com15af88b2016-05-11 20:54:09 +000010313 patchpoint->append(m_tagMask, ValueRep::lateReg(GPRInfo::tagMaskRegister));
10314 patchpoint->append(m_tagTypeNumber, ValueRep::lateReg(GPRInfo::tagTypeNumberRegister));
fpizlo@apple.comac56fba2016-01-08 01:10:15 +000010315 RefPtr<PatchpointExceptionHandle> exceptionHandle =
10316 preparePatchpointForExceptions(patchpoint);
fpizlo@apple.comfee31e22016-01-04 22:31:45 +000010317 patchpoint->numGPScratchRegisters = 1;
10318 patchpoint->clobber(RegisterSet::macroScratchRegisters());
fpizlo@apple.com8cf609a2016-07-21 05:24:54 +000010319 patchpoint->resultConstraint = ValueRep::SomeEarlyRegister;
fpizlo@apple.comfee31e22016-01-04 22:31:45 +000010320 State* state = &m_ftlState;
10321 patchpoint->setGenerator(
10322 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
10323 AllowMacroScratchRegisterUsage allowScratch(jit);
10324
fpizlo@apple.comac56fba2016-01-08 01:10:15 +000010325 Box<CCallHelpers::JumpList> exceptions =
10326 exceptionHandle->scheduleExitCreation(params)->jumps(jit);
10327
fpizlo@apple.comfee31e22016-01-04 22:31:45 +000010328 auto generator = Box<BinaryBitOpGenerator>::create(
10329 leftOperand, rightOperand, JSValueRegs(params[0].gpr()),
10330 JSValueRegs(params[1].gpr()), JSValueRegs(params[2].gpr()), params.gpScratch(0));
10331
10332 generator->generateFastPath(jit);
10333 generator->endJumpList().link(&jit);
10334 CCallHelpers::Label done = jit.label();
10335
10336 params.addLatePath(
10337 [=] (CCallHelpers& jit) {
10338 AllowMacroScratchRegisterUsage allowScratch(jit);
10339
fpizlo@apple.comfee31e22016-01-04 22:31:45 +000010340 generator->slowPathJumpList().link(&jit);
10341 callOperation(
10342 *state, params.unavailableRegisters(), jit, node->origin.semantic,
fpizlo@apple.comac56fba2016-01-08 01:10:15 +000010343 exceptions.get(), slowPathFunction, params[0].gpr(),
10344 params[1].gpr(), params[2].gpr());
fpizlo@apple.comfee31e22016-01-04 22:31:45 +000010345 jit.jump().linkTo(done, &jit);
10346 });
10347 });
10348
10349 setJSValue(patchpoint);
10350 }
fpizlo@apple.com905e5722016-01-04 23:08:32 +000010351
10352 void emitRightShiftSnippet(JITRightShiftGenerator::ShiftType shiftType)
10353 {
10354 Node* node = m_node;
10355
10356 // FIXME: Make this do exceptions.
10357 // https://bugs.webkit.org/show_bug.cgi?id=151686
10358
10359 LValue left = lowJSValue(node->child1());
10360 LValue right = lowJSValue(node->child2());
10361
10362 SnippetOperand leftOperand(m_state.forNode(node->child1()).resultType());
10363 SnippetOperand rightOperand(m_state.forNode(node->child2()).resultType());
10364
10365 PatchpointValue* patchpoint = m_out.patchpoint(Int64);
fpizlo@apple.com45e45652016-01-07 21:20:37 +000010366 patchpoint->appendSomeRegister(left);
10367 patchpoint->appendSomeRegister(right);
sbarati@apple.com15af88b2016-05-11 20:54:09 +000010368 patchpoint->append(m_tagMask, ValueRep::lateReg(GPRInfo::tagMaskRegister));
10369 patchpoint->append(m_tagTypeNumber, ValueRep::lateReg(GPRInfo::tagTypeNumberRegister));
fpizlo@apple.comac56fba2016-01-08 01:10:15 +000010370 RefPtr<PatchpointExceptionHandle> exceptionHandle =
10371 preparePatchpointForExceptions(patchpoint);
fpizlo@apple.com905e5722016-01-04 23:08:32 +000010372 patchpoint->numGPScratchRegisters = 1;
10373 patchpoint->numFPScratchRegisters = 1;
10374 patchpoint->clobber(RegisterSet::macroScratchRegisters());
fpizlo@apple.com8cf609a2016-07-21 05:24:54 +000010375 patchpoint->resultConstraint = ValueRep::SomeEarlyRegister;
fpizlo@apple.com905e5722016-01-04 23:08:32 +000010376 State* state = &m_ftlState;
10377 patchpoint->setGenerator(
10378 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
10379 AllowMacroScratchRegisterUsage allowScratch(jit);
10380
fpizlo@apple.comac56fba2016-01-08 01:10:15 +000010381 Box<CCallHelpers::JumpList> exceptions =
10382 exceptionHandle->scheduleExitCreation(params)->jumps(jit);
10383
fpizlo@apple.com905e5722016-01-04 23:08:32 +000010384 auto generator = Box<JITRightShiftGenerator>::create(
10385 leftOperand, rightOperand, JSValueRegs(params[0].gpr()),
10386 JSValueRegs(params[1].gpr()), JSValueRegs(params[2].gpr()),
10387 params.fpScratch(0), params.gpScratch(0), InvalidFPRReg, shiftType);
10388
10389 generator->generateFastPath(jit);
10390 generator->endJumpList().link(&jit);
10391 CCallHelpers::Label done = jit.label();
10392
10393 params.addLatePath(
10394 [=] (CCallHelpers& jit) {
10395 AllowMacroScratchRegisterUsage allowScratch(jit);
10396
fpizlo@apple.com905e5722016-01-04 23:08:32 +000010397 generator->slowPathJumpList().link(&jit);
10398
10399 J_JITOperation_EJJ slowPathFunction =
10400 shiftType == JITRightShiftGenerator::SignedShift
10401 ? operationValueBitRShift : operationValueBitURShift;
10402
10403 callOperation(
10404 *state, params.unavailableRegisters(), jit, node->origin.semantic,
fpizlo@apple.comac56fba2016-01-08 01:10:15 +000010405 exceptions.get(), slowPathFunction, params[0].gpr(),
10406 params[1].gpr(), params[2].gpr());
fpizlo@apple.com905e5722016-01-04 23:08:32 +000010407 jit.jump().linkTo(done, &jit);
10408 });
10409 });
10410
10411 setJSValue(patchpoint);
10412 }
fpizlo@apple.comb19cd822016-01-04 20:49:33 +000010413
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010414 LValue allocateHeapCell(LValue allocator, LBasicBlock slowPath)
fpizlo@apple.com1002a1d2013-11-06 04:40:02 +000010415 {
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010416 MarkedAllocator* actualAllocator = nullptr;
10417 if (allocator->hasIntPtr())
10418 actualAllocator = bitwise_cast<MarkedAllocator*>(allocator->asIntPtr());
10419
10420 if (!actualAllocator) {
10421 // This means that either we know that the allocator is null or we don't know what the
10422 // allocator is. In either case, we need the null check.
10423 LBasicBlock haveAllocator = m_out.newBlock();
10424 LBasicBlock lastNext = m_out.insertNewBlocksBefore(haveAllocator);
10425 m_out.branch(allocator, usually(haveAllocator), rarely(slowPath));
10426 m_out.appendTo(haveAllocator, lastNext);
sbarati@apple.comfa3be3e2015-10-31 09:15:35 +000010427 }
fpizlo@apple.com1002a1d2013-11-06 04:40:02 +000010428
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010429 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com1002a1d2013-11-06 04:40:02 +000010430
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010431 LBasicBlock lastNext = m_out.insertNewBlocksBefore(continuation);
10432
10433 PatchpointValue* patchpoint = m_out.patchpoint(pointerType());
10434 patchpoint->effects.terminal = true;
10435 patchpoint->appendSomeRegister(allocator);
10436 patchpoint->numGPScratchRegisters++;
10437 patchpoint->resultConstraint = ValueRep::SomeEarlyRegister;
10438
10439 m_out.appendSuccessor(usually(continuation));
10440 m_out.appendSuccessor(rarely(slowPath));
10441
10442 patchpoint->setGenerator(
10443 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
10444 CCallHelpers::JumpList jumpToSlowPath;
10445
10446 // We use a patchpoint to emit the allocation path because whenever we mess with
10447 // allocation paths, we already reason about them at the machine code level. We know
10448 // exactly what instruction sequence we want. We're confident that no compiler
10449 // optimization could make this code better. So, it's best to have the code in
10450 // AssemblyHelpers::emitAllocate(). That way, the same optimized path is shared by
10451 // all of the compiler tiers.
10452 jit.emitAllocateWithNonNullAllocator(
10453 params[0].gpr(), actualAllocator, params[1].gpr(), params.gpScratch(0),
10454 jumpToSlowPath);
10455
10456 CCallHelpers::Jump jumpToSuccess;
10457 if (!params.fallsThroughToSuccessor(0))
10458 jumpToSuccess = jit.jump();
10459
10460 Vector<Box<CCallHelpers::Label>> labels = params.successorLabels();
10461
10462 params.addLatePath(
10463 [=] (CCallHelpers& jit) {
10464 jumpToSlowPath.linkTo(*labels[1], &jit);
10465 if (jumpToSuccess.isSet())
10466 jumpToSuccess.linkTo(*labels[0], &jit);
10467 });
10468 });
10469
10470 m_out.appendTo(continuation, lastNext);
10471 return patchpoint;
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000010472 }
commit-queue@webkit.org3194ff32016-11-30 20:30:16 +000010473
10474 void storeStructure(LValue object, Structure* structure)
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000010475 {
commit-queue@webkit.org3194ff32016-11-30 20:30:16 +000010476 m_out.store32(m_out.constInt32(structure->id()), object, m_heaps.JSCell_structureID);
10477 m_out.store32(
10478 m_out.constInt32(structure->objectInitializationBlob()),
10479 object, m_heaps.JSCell_usefulBytes);
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000010480 }
10481
sbarati@apple.comfd407a52017-01-13 04:03:47 +000010482 void storeStructure(LValue object, LValue structure)
10483 {
10484 if (structure->hasIntPtr()) {
10485 storeStructure(object, bitwise_cast<Structure*>(structure->asIntPtr()));
10486 return;
10487 }
10488
10489 LValue id = m_out.load32(structure, m_heaps.Structure_structureID);
10490 m_out.store32(id, object, m_heaps.JSCell_structureID);
10491
10492 LValue blob = m_out.load32(structure, m_heaps.Structure_indexingTypeIncludingHistory);
10493 m_out.store32(blob, object, m_heaps.JSCell_usefulBytes);
10494 }
10495
10496 template <typename StructureType>
10497 LValue allocateCell(LValue allocator, StructureType structure, LBasicBlock slowPath)
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000010498 {
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010499 LValue result = allocateHeapCell(allocator, slowPath);
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000010500 storeStructure(result, structure);
fpizlo@apple.com1002a1d2013-11-06 04:40:02 +000010501 return result;
10502 }
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +000010503
sbarati@apple.com239d20b2017-01-26 23:50:58 +000010504 LValue allocateObject(LValue allocator, RegisteredStructure structure, LValue butterfly, LBasicBlock slowPath)
sbarati@apple.comfd407a52017-01-13 04:03:47 +000010505 {
sbarati@apple.com239d20b2017-01-26 23:50:58 +000010506 return allocateObject(allocator, weakStructure(structure), butterfly, slowPath);
sbarati@apple.comfd407a52017-01-13 04:03:47 +000010507 }
10508
10509 LValue allocateObject(LValue allocator, LValue structure, LValue butterfly, LBasicBlock slowPath)
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +000010510 {
10511 LValue result = allocateCell(allocator, structure, slowPath);
sbarati@apple.comfd407a52017-01-13 04:03:47 +000010512 if (structure->hasIntPtr()) {
10513 splatWords(
10514 result,
10515 m_out.constInt32(JSFinalObject::offsetOfInlineStorage() / 8),
10516 m_out.constInt32(JSFinalObject::offsetOfInlineStorage() / 8 + bitwise_cast<Structure*>(structure->asIntPtr())->inlineCapacity()),
10517 m_out.int64Zero,
10518 m_heaps.properties.atAnyNumber());
10519 } else {
10520 LValue end = m_out.add(
10521 m_out.constInt32(JSFinalObject::offsetOfInlineStorage() / 8),
10522 m_out.load8ZeroExt32(structure, m_heaps.Structure_inlineCapacity));
10523 splatWords(
10524 result,
10525 m_out.constInt32(JSFinalObject::offsetOfInlineStorage() / 8),
10526 end,
10527 m_out.int64Zero,
10528 m_heaps.properties.atAnyNumber());
10529 }
10530
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +000010531 m_out.storePtr(butterfly, result, m_heaps.JSObject_butterfly);
10532 return result;
10533 }
10534
sbarati@apple.comfd407a52017-01-13 04:03:47 +000010535 template<typename ClassType, typename StructureType>
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000010536 LValue allocateObject(
sbarati@apple.comfd407a52017-01-13 04:03:47 +000010537 size_t size, StructureType structure, LValue butterfly, LBasicBlock slowPath)
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +000010538 {
fpizlo@apple.com5fa9d962017-01-18 04:22:45 +000010539 MarkedAllocator* allocator = subspaceFor<ClassType>(vm())->allocatorFor(size);
commit-queue@webkit.org3194ff32016-11-30 20:30:16 +000010540 return allocateObject(m_out.constIntPtr(allocator), structure, butterfly, slowPath);
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +000010541 }
10542
sbarati@apple.comfd407a52017-01-13 04:03:47 +000010543 template<typename ClassType, typename StructureType>
10544 LValue allocateObject(StructureType structure, LValue butterfly, LBasicBlock slowPath)
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000010545 {
10546 return allocateObject<ClassType>(
10547 ClassType::allocationSize(0), structure, butterfly, slowPath);
10548 }
10549
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010550 LValue allocatorForSize(LValue subspace, LValue size, LBasicBlock slowPath)
10551 {
10552 static_assert(!(MarkedSpace::sizeStep & (MarkedSpace::sizeStep - 1)), "MarkedSpace::sizeStep must be a power of two.");
10553
10554 // Try to do some constant-folding here.
10555 if (subspace->hasIntPtr() && size->hasIntPtr()) {
fpizlo@apple.com5fa9d962017-01-18 04:22:45 +000010556 Subspace* actualSubspace = bitwise_cast<Subspace*>(subspace->asIntPtr());
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010557 size_t actualSize = size->asIntPtr();
10558
fpizlo@apple.com5fa9d962017-01-18 04:22:45 +000010559 MarkedAllocator* actualAllocator = actualSubspace->allocatorFor(actualSize);
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010560 if (!actualAllocator) {
10561 LBasicBlock continuation = m_out.newBlock();
10562 LBasicBlock lastNext = m_out.insertNewBlocksBefore(continuation);
10563 m_out.jump(slowPath);
10564 m_out.appendTo(continuation, lastNext);
10565 return m_out.intPtrZero;
10566 }
10567
10568 return m_out.constIntPtr(actualAllocator);
10569 }
10570
10571 unsigned stepShift = getLSBSet(MarkedSpace::sizeStep);
10572
10573 LBasicBlock continuation = m_out.newBlock();
10574
10575 LBasicBlock lastNext = m_out.insertNewBlocksBefore(continuation);
10576
10577 LValue sizeClassIndex = m_out.lShr(
10578 m_out.add(size, m_out.constIntPtr(MarkedSpace::sizeStep - 1)),
10579 m_out.constInt32(stepShift));
10580
10581 m_out.branch(
10582 m_out.above(sizeClassIndex, m_out.constIntPtr(MarkedSpace::largeCutoff >> stepShift)),
10583 rarely(slowPath), usually(continuation));
10584
10585 m_out.appendTo(continuation, lastNext);
10586
10587 return m_out.loadPtr(
10588 m_out.baseIndex(
fpizlo@apple.com5fa9d962017-01-18 04:22:45 +000010589 m_heaps.Subspace_allocatorForSizeStep,
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010590 subspace, m_out.sub(sizeClassIndex, m_out.intPtrOne)));
10591 }
10592
fpizlo@apple.com5fa9d962017-01-18 04:22:45 +000010593 LValue allocatorForSize(Subspace& subspace, LValue size, LBasicBlock slowPath)
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010594 {
10595 return allocatorForSize(m_out.constIntPtr(&subspace), size, slowPath);
10596 }
10597
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000010598 template<typename ClassType>
10599 LValue allocateVariableSizedObject(
sbarati@apple.com239d20b2017-01-26 23:50:58 +000010600 LValue size, RegisteredStructure structure, LValue butterfly, LBasicBlock slowPath)
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000010601 {
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010602 LValue allocator = allocatorForSize(
fpizlo@apple.com5fa9d962017-01-18 04:22:45 +000010603 *subspaceFor<ClassType>(vm()), size, slowPath);
commit-queue@webkit.org3194ff32016-11-30 20:30:16 +000010604 return allocateObject(allocator, structure, butterfly, slowPath);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000010605 }
sbarati@apple.com99ed4792016-11-12 02:58:11 +000010606
10607 template<typename ClassType>
10608 LValue allocateVariableSizedCell(
10609 LValue size, Structure* structure, LBasicBlock slowPath)
10610 {
10611 LValue allocator = allocatorForSize(
fpizlo@apple.com5fa9d962017-01-18 04:22:45 +000010612 *subspaceFor<ClassType>(vm()), size, slowPath);
commit-queue@webkit.org3194ff32016-11-30 20:30:16 +000010613 return allocateCell(allocator, structure, slowPath);
sbarati@apple.com99ed4792016-11-12 02:58:11 +000010614 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000010615
sbarati@apple.com239d20b2017-01-26 23:50:58 +000010616 LValue allocateObject(RegisteredStructure structure)
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000010617 {
sbarati@apple.com239d20b2017-01-26 23:50:58 +000010618 size_t allocationSize = JSFinalObject::allocationSize(structure.get()->inlineCapacity());
fpizlo@apple.com5fa9d962017-01-18 04:22:45 +000010619 MarkedAllocator* allocator = subspaceFor<JSFinalObject>(vm())->allocatorFor(allocationSize);
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010620
10621 // FIXME: If the allocator is null, we could simply emit a normal C call to the allocator
10622 // instead of putting it on the slow path.
10623 // https://bugs.webkit.org/show_bug.cgi?id=161062
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000010624
fpizlo@apple.com91331742016-03-07 02:07:28 +000010625 LBasicBlock slowPath = m_out.newBlock();
10626 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000010627
10628 LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
10629
10630 ValueFromBlock fastResult = m_out.anchor(allocateObject(
commit-queue@webkit.org3194ff32016-11-30 20:30:16 +000010631 m_out.constIntPtr(allocator), structure, m_out.intPtrZero, slowPath));
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000010632
10633 m_out.jump(continuation);
10634
10635 m_out.appendTo(slowPath, continuation);
fpizlo@apple.com6e697962015-10-12 17:56:26 +000010636
10637 LValue slowResultValue = lazySlowPath(
10638 [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
10639 return createLazyCallGenerator(
10640 operationNewObject, locations[0].directGPR(),
sbarati@apple.com239d20b2017-01-26 23:50:58 +000010641 CCallHelpers::TrustedImmPtr(structure.get()));
fpizlo@apple.com6e697962015-10-12 17:56:26 +000010642 });
10643 ValueFromBlock slowResult = m_out.anchor(slowResultValue);
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000010644 m_out.jump(continuation);
10645
10646 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +000010647 return m_out.phi(pointerType(), fastResult, slowResult);
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000010648 }
10649
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +000010650 struct ArrayValues {
10651 ArrayValues()
10652 : array(0)
10653 , butterfly(0)
10654 {
10655 }
10656
10657 ArrayValues(LValue array, LValue butterfly)
10658 : array(array)
10659 , butterfly(butterfly)
10660 {
10661 }
10662
10663 LValue array;
10664 LValue butterfly;
10665 };
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010666
sbarati@apple.comfd407a52017-01-13 04:03:47 +000010667 ArrayValues allocateJSArray(LValue publicLength, LValue structure, LValue indexingType, bool shouldInitializeElements = true, bool shouldLargeArraySizeCreateArrayStorage = true)
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +000010668 {
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010669 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
sbarati@apple.comfd407a52017-01-13 04:03:47 +000010670 if (indexingType->hasInt32()) {
10671 IndexingType type = static_cast<IndexingType>(indexingType->asInt32());
10672 ASSERT_UNUSED(type,
10673 hasUndecided(type)
10674 || hasInt32(type)
10675 || hasDouble(type)
10676 || hasContiguous(type));
10677 }
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010678
10679 LBasicBlock fastCase = m_out.newBlock();
10680 LBasicBlock largeCase = m_out.newBlock();
10681 LBasicBlock failCase = m_out.newBlock();
10682 LBasicBlock continuation = m_out.newBlock();
10683 LBasicBlock slowCase = m_out.newBlock();
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +000010684
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010685 LBasicBlock lastNext = m_out.insertNewBlocksBefore(fastCase);
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +000010686
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010687 ValueFromBlock noButterfly = m_out.anchor(m_out.intPtrZero);
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +000010688
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010689 LValue predicate;
10690 if (shouldLargeArraySizeCreateArrayStorage)
10691 predicate = m_out.aboveOrEqual(publicLength, m_out.constInt32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH));
10692 else
10693 predicate = m_out.booleanFalse;
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +000010694
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010695 m_out.branch(predicate, rarely(largeCase), usually(fastCase));
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +000010696
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010697 m_out.appendTo(fastCase, largeCase);
10698
10699 LValue vectorLength = nullptr;
sbarati@apple.comfd407a52017-01-13 04:03:47 +000010700 if (publicLength->hasInt32() && structure->hasIntPtr()) {
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010701 unsigned publicLengthConst = static_cast<unsigned>(publicLength->asInt32());
10702 if (publicLengthConst <= MAX_STORAGE_VECTOR_LENGTH) {
10703 vectorLength = m_out.constInt32(
10704 Butterfly::optimalContiguousVectorLength(
sbarati@apple.comfd407a52017-01-13 04:03:47 +000010705 bitwise_cast<Structure*>(structure->asIntPtr())->outOfLineCapacity(), publicLengthConst));
fpizlo@apple.com595eebd2016-08-24 19:00:37 +000010706 }
10707 }
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +000010708
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010709 if (!vectorLength) {
10710 // We don't compute the optimal vector length for new Array(blah) where blah is not
10711 // statically known, since the compute effort of doing it here is probably not worth it.
10712 vectorLength = publicLength;
10713 }
10714
10715 LValue payloadSize =
10716 m_out.shl(m_out.zeroExt(vectorLength, pointerType()), m_out.constIntPtr(3));
10717
10718 LValue butterflySize = m_out.add(
10719 payloadSize, m_out.constIntPtr(sizeof(IndexingHeader)));
10720
fpizlo@apple.com5fa9d962017-01-18 04:22:45 +000010721 LValue allocator = allocatorForSize(vm().auxiliarySpace, butterflySize, failCase);
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010722 LValue startOfStorage = allocateHeapCell(allocator, failCase);
10723
10724 LValue butterfly = m_out.add(startOfStorage, m_out.constIntPtr(sizeof(IndexingHeader)));
10725
10726 m_out.store32(publicLength, butterfly, m_heaps.Butterfly_publicLength);
10727 m_out.store32(vectorLength, butterfly, m_heaps.Butterfly_vectorLength);
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +000010728
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010729 initializeArrayElements(
10730 indexingType,
10731 shouldInitializeElements ? m_out.int32Zero : publicLength, vectorLength,
10732 butterfly);
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +000010733
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010734 ValueFromBlock haveButterfly = m_out.anchor(butterfly);
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +000010735
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010736 LValue object = allocateObject<JSArray>(structure, butterfly, failCase);
sbarati@apple.comfd407a52017-01-13 04:03:47 +000010737
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010738 ValueFromBlock fastResult = m_out.anchor(object);
10739 ValueFromBlock fastButterfly = m_out.anchor(butterfly);
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +000010740 m_out.jump(continuation);
10741
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010742 m_out.appendTo(largeCase, failCase);
10743 ValueFromBlock largeStructure = m_out.anchor(
sbarati@apple.com239d20b2017-01-26 23:50:58 +000010744 weakStructure(m_graph.registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage))));
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010745 m_out.jump(slowCase);
10746
10747 m_out.appendTo(failCase, slowCase);
sbarati@apple.comfd407a52017-01-13 04:03:47 +000010748 ValueFromBlock failStructure = m_out.anchor(structure);
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010749 m_out.jump(slowCase);
10750
10751 m_out.appendTo(slowCase, continuation);
10752 LValue structureValue = m_out.phi(pointerType(), largeStructure, failStructure);
10753 LValue butterflyValue = m_out.phi(pointerType(), noButterfly, haveButterfly);
fpizlo@apple.com6e697962015-10-12 17:56:26 +000010754
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010755 LValue slowResultValue = lazySlowPath(
fpizlo@apple.com6e697962015-10-12 17:56:26 +000010756 [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
10757 return createLazyCallGenerator(
10758 operationNewArrayWithSize, locations[0].directGPR(),
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010759 locations[1].directGPR(), locations[2].directGPR(), locations[3].directGPR());
10760 },
10761 structureValue, publicLength, butterflyValue);
10762 ValueFromBlock slowResult = m_out.anchor(slowResultValue);
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +000010763 ValueFromBlock slowButterfly = m_out.anchor(
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010764 m_out.loadPtr(slowResultValue, m_heaps.JSObject_butterfly));
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +000010765 m_out.jump(continuation);
10766
10767 m_out.appendTo(continuation, lastNext);
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +000010768 return ArrayValues(
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010769 m_out.phi(pointerType(), fastResult, slowResult),
fpizlo@apple.com994d4532016-07-03 19:34:55 +000010770 m_out.phi(pointerType(), fastButterfly, slowButterfly));
fpizlo@apple.comc081a0e2013-11-08 01:55:49 +000010771 }
10772
sbarati@apple.com239d20b2017-01-26 23:50:58 +000010773 ArrayValues allocateUninitializedContiguousJSArray(LValue publicLength, RegisteredStructure structure)
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010774 {
10775 bool shouldInitializeElements = false;
10776 bool shouldLargeArraySizeCreateArrayStorage = false;
10777 return allocateJSArray(
sbarati@apple.com239d20b2017-01-26 23:50:58 +000010778 publicLength, weakStructure(structure), m_out.constInt32(structure->indexingType()), shouldInitializeElements,
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000010779 shouldLargeArraySizeCreateArrayStorage);
10780 }
10781
sbarati@apple.comce5b05e2016-05-16 23:31:39 +000010782 LValue ensureShadowChickenPacket()
fpizlo@apple.com39303e02016-04-05 22:17:35 +000010783 {
10784 LBasicBlock slowCase = m_out.newBlock();
10785 LBasicBlock continuation = m_out.newBlock();
10786
10787 TypedPointer addressOfLogCursor = m_out.absolute(vm().shadowChicken().addressOfLogCursor());
10788 LValue logCursor = m_out.loadPtr(addressOfLogCursor);
10789
10790 ValueFromBlock fastResult = m_out.anchor(logCursor);
10791
10792 m_out.branch(
10793 m_out.below(logCursor, m_out.constIntPtr(vm().shadowChicken().logEnd())),
10794 usually(continuation), rarely(slowCase));
10795
10796 LBasicBlock lastNext = m_out.appendTo(slowCase, continuation);
10797
10798 vmCall(Void, m_out.operation(operationProcessShadowChickenLog), m_callFrame);
10799
10800 ValueFromBlock slowResult = m_out.anchor(m_out.loadPtr(addressOfLogCursor));
10801 m_out.jump(continuation);
10802
10803 m_out.appendTo(continuation, lastNext);
10804 LValue result = m_out.phi(pointerType(), fastResult, slowResult);
10805
10806 m_out.storePtr(
10807 m_out.add(result, m_out.constIntPtr(sizeof(ShadowChicken::Packet))),
10808 addressOfLogCursor);
10809
10810 return result;
10811 }
10812
oliver@apple.comec61ab22013-07-25 04:01:02 +000010813 LValue boolify(Edge edge)
10814 {
10815 switch (edge.useKind()) {
10816 case BooleanUse:
fpizlo@apple.com7289af32015-08-21 03:59:33 +000010817 case KnownBooleanUse:
fpizlo@apple.com5b9b41b2015-05-29 20:26:37 +000010818 return lowBoolean(edge);
oliver@apple.comec61ab22013-07-25 04:01:02 +000010819 case Int32Use:
fpizlo@apple.com5b9b41b2015-05-29 20:26:37 +000010820 return m_out.notZero32(lowInt32(edge));
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +000010821 case DoubleRepUse:
commit-queue@webkit.orgbd1d1d32015-12-19 16:52:11 +000010822 return m_out.doubleNotEqualAndOrdered(lowDouble(edge), m_out.doubleZero);
oliver@apple.comfdbb0862013-07-25 04:01:03 +000010823 case ObjectOrOtherUse:
fpizlo@apple.com959a2c42015-12-22 21:59:59 +000010824 return m_out.logicalNot(
oliver@apple.comfdbb0862013-07-25 04:01:03 +000010825 equalNullOrUndefined(
10826 edge, CellCaseSpeculatesObject, SpeculateNullOrUndefined,
10827 ManualOperandSpeculation));
mark.lam@apple.com67e54e92013-10-14 23:30:37 +000010828 case StringUse: {
fpizlo@apple.com5b9b41b2015-05-29 20:26:37 +000010829 LValue stringValue = lowString(edge);
msaboff@apple.com95894332014-01-29 19:18:54 +000010830 LValue length = m_out.load32NonNegative(stringValue, m_heaps.JSString_length);
mark.lam@apple.com67e54e92013-10-14 23:30:37 +000010831 return m_out.notEqual(length, m_out.int32Zero);
10832 }
fpizlo@apple.com91331742016-03-07 02:07:28 +000010833 case StringOrOtherUse: {
10834 LValue value = lowJSValue(edge, ManualOperandSpeculation);
10835
10836 LBasicBlock cellCase = m_out.newBlock();
10837 LBasicBlock notCellCase = m_out.newBlock();
10838 LBasicBlock continuation = m_out.newBlock();
10839
10840 m_out.branch(isCell(value, provenType(edge)), unsure(cellCase), unsure(notCellCase));
10841
10842 LBasicBlock lastNext = m_out.appendTo(cellCase, notCellCase);
10843
10844 FTL_TYPE_CHECK(jsValueValue(value), edge, (~SpecCell) | SpecString, isNotString(value));
10845 LValue length = m_out.load32NonNegative(value, m_heaps.JSString_length);
10846 ValueFromBlock cellResult = m_out.anchor(m_out.notEqual(length, m_out.int32Zero));
10847 m_out.jump(continuation);
10848
10849 m_out.appendTo(notCellCase, continuation);
10850
10851 FTL_TYPE_CHECK(jsValueValue(value), edge, SpecCell | SpecOther, isNotOther(value));
10852 ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse);
10853 m_out.jump(continuation);
10854 m_out.appendTo(continuation, lastNext);
10855
10856 return m_out.phi(Int32, cellResult, notCellResult);
10857 }
fpizlo@apple.com10648ef2013-12-06 23:20:09 +000010858 case UntypedUse: {
fpizlo@apple.com5b9b41b2015-05-29 20:26:37 +000010859 LValue value = lowJSValue(edge);
fpizlo@apple.com10648ef2013-12-06 23:20:09 +000010860
fpizlo@apple.com5b9b41b2015-05-29 20:26:37 +000010861 // Implements the following control flow structure:
10862 // if (value is cell) {
10863 // if (value is string)
10864 // result = !!value->length
10865 // else {
10866 // do evil things for masquerades-as-undefined
10867 // result = true
10868 // }
10869 // } else if (value is int32) {
10870 // result = !!unboxInt32(value)
10871 // } else if (value is number) {
10872 // result = !!unboxDouble(value)
10873 // } else {
10874 // result = value == jsTrue
10875 // }
10876
fpizlo@apple.com91331742016-03-07 02:07:28 +000010877 LBasicBlock cellCase = m_out.newBlock();
10878 LBasicBlock stringCase = m_out.newBlock();
10879 LBasicBlock notStringCase = m_out.newBlock();
10880 LBasicBlock notCellCase = m_out.newBlock();
10881 LBasicBlock int32Case = m_out.newBlock();
10882 LBasicBlock notInt32Case = m_out.newBlock();
10883 LBasicBlock doubleCase = m_out.newBlock();
10884 LBasicBlock notDoubleCase = m_out.newBlock();
10885 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com10648ef2013-12-06 23:20:09 +000010886
fpizlo@apple.com5b9b41b2015-05-29 20:26:37 +000010887 Vector<ValueFromBlock> results;
fpizlo@apple.com10648ef2013-12-06 23:20:09 +000010888
fpizlo@apple.com5b9b41b2015-05-29 20:26:37 +000010889 m_out.branch(isCell(value, provenType(edge)), unsure(cellCase), unsure(notCellCase));
10890
10891 LBasicBlock lastNext = m_out.appendTo(cellCase, stringCase);
10892 m_out.branch(
10893 isString(value, provenType(edge) & SpecCell),
10894 unsure(stringCase), unsure(notStringCase));
10895
10896 m_out.appendTo(stringCase, notStringCase);
10897 LValue nonEmptyString = m_out.notZero32(
10898 m_out.load32NonNegative(value, m_heaps.JSString_length));
10899 results.append(m_out.anchor(nonEmptyString));
fpizlo@apple.com10648ef2013-12-06 23:20:09 +000010900 m_out.jump(continuation);
10901
fpizlo@apple.com5b9b41b2015-05-29 20:26:37 +000010902 m_out.appendTo(notStringCase, notCellCase);
10903 LValue isTruthyObject;
10904 if (masqueradesAsUndefinedWatchpointIsStillValid())
10905 isTruthyObject = m_out.booleanTrue;
10906 else {
fpizlo@apple.com91331742016-03-07 02:07:28 +000010907 LBasicBlock masqueradesCase = m_out.newBlock();
fpizlo@apple.com5b9b41b2015-05-29 20:26:37 +000010908
fpizlo@apple.coma61e9a82015-06-16 19:17:40 +000010909 results.append(m_out.anchor(m_out.booleanTrue));
fpizlo@apple.com5b9b41b2015-05-29 20:26:37 +000010910
10911 m_out.branch(
benjamin@webkit.org2e864d22015-11-17 06:20:21 +000010912 m_out.testIsZero32(
10913 m_out.load8ZeroExt32(value, m_heaps.JSCell_typeInfoFlags),
10914 m_out.constInt32(MasqueradesAsUndefined)),
fpizlo@apple.com5b9b41b2015-05-29 20:26:37 +000010915 usually(continuation), rarely(masqueradesCase));
10916
10917 m_out.appendTo(masqueradesCase);
10918
10919 isTruthyObject = m_out.notEqual(
sbarati@apple.com239d20b2017-01-26 23:50:58 +000010920 weakPointer(m_graph.globalObjectFor(m_node->origin.semantic)),
fpizlo@apple.com5b9b41b2015-05-29 20:26:37 +000010921 m_out.loadPtr(loadStructure(value), m_heaps.Structure_globalObject));
10922 }
10923 results.append(m_out.anchor(isTruthyObject));
10924 m_out.jump(continuation);
10925
10926 m_out.appendTo(notCellCase, int32Case);
10927 m_out.branch(
10928 isInt32(value, provenType(edge) & ~SpecCell),
10929 unsure(int32Case), unsure(notInt32Case));
10930
10931 m_out.appendTo(int32Case, notInt32Case);
10932 results.append(m_out.anchor(m_out.notZero32(unboxInt32(value))));
10933 m_out.jump(continuation);
10934
10935 m_out.appendTo(notInt32Case, doubleCase);
10936 m_out.branch(
10937 isNumber(value, provenType(edge) & ~SpecCell),
10938 unsure(doubleCase), unsure(notDoubleCase));
10939
10940 m_out.appendTo(doubleCase, notDoubleCase);
commit-queue@webkit.orgbd1d1d32015-12-19 16:52:11 +000010941 LValue doubleIsTruthy = m_out.doubleNotEqualAndOrdered(
fpizlo@apple.com5b9b41b2015-05-29 20:26:37 +000010942 unboxDouble(value), m_out.constDouble(0));
10943 results.append(m_out.anchor(doubleIsTruthy));
10944 m_out.jump(continuation);
10945
10946 m_out.appendTo(notDoubleCase, continuation);
10947 LValue miscIsTruthy = m_out.equal(
10948 value, m_out.constInt64(JSValue::encode(jsBoolean(true))));
10949 results.append(m_out.anchor(miscIsTruthy));
fpizlo@apple.com10648ef2013-12-06 23:20:09 +000010950 m_out.jump(continuation);
10951
10952 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +000010953 return m_out.phi(Int32, results);
fpizlo@apple.com10648ef2013-12-06 23:20:09 +000010954 }
oliver@apple.comec61ab22013-07-25 04:01:02 +000010955 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +000010956 DFG_CRASH(m_graph, m_node, "Bad use kind");
oliver@apple.comec61ab22013-07-25 04:01:02 +000010957 return 0;
10958 }
10959 }
10960
oliver@apple.comfdbb0862013-07-25 04:01:03 +000010961 enum StringOrObjectMode {
10962 AllCellsAreFalse,
10963 CellCaseSpeculatesObject
10964 };
10965 enum EqualNullOrUndefinedMode {
10966 EqualNull,
10967 EqualUndefined,
10968 EqualNullOrUndefined,
10969 SpeculateNullOrUndefined
10970 };
10971 LValue equalNullOrUndefined(
10972 Edge edge, StringOrObjectMode cellMode, EqualNullOrUndefinedMode primitiveMode,
10973 OperandSpeculationMode operandMode = AutomaticOperandSpeculation)
oliver@apple.com9a58da12013-07-25 04:00:00 +000010974 {
fpizlo@apple.comd84425d2013-10-30 19:58:08 +000010975 bool validWatchpoint = masqueradesAsUndefinedWatchpointIsStillValid();
oliver@apple.com9a58da12013-07-25 04:00:00 +000010976
oliver@apple.comfdbb0862013-07-25 04:01:03 +000010977 LValue value = lowJSValue(edge, operandMode);
oliver@apple.com9a58da12013-07-25 04:00:00 +000010978
fpizlo@apple.com91331742016-03-07 02:07:28 +000010979 LBasicBlock cellCase = m_out.newBlock();
10980 LBasicBlock primitiveCase = m_out.newBlock();
10981 LBasicBlock continuation = m_out.newBlock();
oliver@apple.com9a58da12013-07-25 04:00:00 +000010982
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000010983 m_out.branch(isNotCell(value, provenType(edge)), unsure(primitiveCase), unsure(cellCase));
oliver@apple.com9a58da12013-07-25 04:00:00 +000010984
10985 LBasicBlock lastNext = m_out.appendTo(cellCase, primitiveCase);
10986
10987 Vector<ValueFromBlock, 3> results;
10988
oliver@apple.comfdbb0862013-07-25 04:01:03 +000010989 switch (cellMode) {
10990 case AllCellsAreFalse:
10991 break;
10992 case CellCaseSpeculatesObject:
10993 FTL_TYPE_CHECK(
utatane.tea@gmail.com0bfb74c2015-02-24 23:01:58 +000010994 jsValueValue(value), edge, (~SpecCell) | SpecObject, isNotObject(value));
oliver@apple.comfdbb0862013-07-25 04:01:03 +000010995 break;
10996 }
10997
oliver@apple.com9a58da12013-07-25 04:00:00 +000010998 if (validWatchpoint) {
10999 results.append(m_out.anchor(m_out.booleanFalse));
11000 m_out.jump(continuation);
11001 } else {
11002 LBasicBlock masqueradesCase =
fpizlo@apple.com91331742016-03-07 02:07:28 +000011003 m_out.newBlock();
oliver@apple.com9a58da12013-07-25 04:00:00 +000011004
oliver@apple.com9a58da12013-07-25 04:00:00 +000011005 results.append(m_out.anchor(m_out.booleanFalse));
11006
11007 m_out.branch(
benjamin@webkit.org2e864d22015-11-17 06:20:21 +000011008 m_out.testNonZero32(
11009 m_out.load8ZeroExt32(value, m_heaps.JSCell_typeInfoFlags),
11010 m_out.constInt32(MasqueradesAsUndefined)),
fpizlo@apple.com975ae502014-02-19 22:29:43 +000011011 rarely(masqueradesCase), usually(continuation));
oliver@apple.com9a58da12013-07-25 04:00:00 +000011012
11013 m_out.appendTo(masqueradesCase, primitiveCase);
11014
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +000011015 LValue structure = loadStructure(value);
11016
oliver@apple.com9a58da12013-07-25 04:00:00 +000011017 results.append(m_out.anchor(
11018 m_out.equal(
sbarati@apple.com239d20b2017-01-26 23:50:58 +000011019 weakPointer(m_graph.globalObjectFor(m_node->origin.semantic)),
oliver@apple.com9a58da12013-07-25 04:00:00 +000011020 m_out.loadPtr(structure, m_heaps.Structure_globalObject))));
11021 m_out.jump(continuation);
11022 }
11023
11024 m_out.appendTo(primitiveCase, continuation);
11025
11026 LValue primitiveResult;
oliver@apple.comfdbb0862013-07-25 04:01:03 +000011027 switch (primitiveMode) {
oliver@apple.com9a58da12013-07-25 04:00:00 +000011028 case EqualNull:
11029 primitiveResult = m_out.equal(value, m_out.constInt64(ValueNull));
11030 break;
11031 case EqualUndefined:
11032 primitiveResult = m_out.equal(value, m_out.constInt64(ValueUndefined));
11033 break;
11034 case EqualNullOrUndefined:
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000011035 primitiveResult = isOther(value, provenType(edge));
oliver@apple.com9a58da12013-07-25 04:00:00 +000011036 break;
oliver@apple.comfdbb0862013-07-25 04:01:03 +000011037 case SpeculateNullOrUndefined:
11038 FTL_TYPE_CHECK(
fpizlo@apple.com312efcd2014-03-10 22:11:35 +000011039 jsValueValue(value), edge, SpecCell | SpecOther, isNotOther(value));
oliver@apple.comfdbb0862013-07-25 04:01:03 +000011040 primitiveResult = m_out.booleanTrue;
11041 break;
oliver@apple.com9a58da12013-07-25 04:00:00 +000011042 }
11043 results.append(m_out.anchor(primitiveResult));
11044 m_out.jump(continuation);
11045
11046 m_out.appendTo(continuation, lastNext);
11047
fpizlo@apple.com994d4532016-07-03 19:34:55 +000011048 return m_out.phi(Int32, results);
oliver@apple.com9a58da12013-07-25 04:00:00 +000011049 }
11050
oliver@apple.com8c55ed02013-07-25 04:04:01 +000011051 template<typename FunctionType>
11052 void contiguousPutByValOutOfBounds(
fpizlo@apple.com8624c4b2013-12-10 03:24:31 +000011053 FunctionType slowPathFunction, LValue base, LValue storage, LValue index, LValue value,
oliver@apple.com8c55ed02013-07-25 04:04:01 +000011054 LBasicBlock continuation)
11055 {
11056 LValue isNotInBounds = m_out.aboveOrEqual(
msaboff@apple.com95894332014-01-29 19:18:54 +000011057 index, m_out.load32NonNegative(storage, m_heaps.Butterfly_publicLength));
fpizlo@apple.com8624c4b2013-12-10 03:24:31 +000011058 if (!m_node->arrayMode().isInBounds()) {
oliver@apple.com8c55ed02013-07-25 04:04:01 +000011059 LBasicBlock notInBoundsCase =
fpizlo@apple.com91331742016-03-07 02:07:28 +000011060 m_out.newBlock();
oliver@apple.com8c55ed02013-07-25 04:04:01 +000011061 LBasicBlock performStore =
fpizlo@apple.com91331742016-03-07 02:07:28 +000011062 m_out.newBlock();
oliver@apple.com8c55ed02013-07-25 04:04:01 +000011063
fpizlo@apple.com975ae502014-02-19 22:29:43 +000011064 m_out.branch(isNotInBounds, unsure(notInBoundsCase), unsure(performStore));
oliver@apple.com8c55ed02013-07-25 04:04:01 +000011065
11066 LBasicBlock lastNext = m_out.appendTo(notInBoundsCase, performStore);
11067
11068 LValue isOutOfBounds = m_out.aboveOrEqual(
msaboff@apple.com95894332014-01-29 19:18:54 +000011069 index, m_out.load32NonNegative(storage, m_heaps.Butterfly_vectorLength));
oliver@apple.com8c55ed02013-07-25 04:04:01 +000011070
11071 if (!m_node->arrayMode().isOutOfBounds())
11072 speculate(OutOfBounds, noValue(), 0, isOutOfBounds);
11073 else {
11074 LBasicBlock outOfBoundsCase =
fpizlo@apple.com91331742016-03-07 02:07:28 +000011075 m_out.newBlock();
oliver@apple.com8c55ed02013-07-25 04:04:01 +000011076 LBasicBlock holeCase =
fpizlo@apple.com91331742016-03-07 02:07:28 +000011077 m_out.newBlock();
oliver@apple.com8c55ed02013-07-25 04:04:01 +000011078
fpizlo@apple.com28c71002016-01-15 19:41:56 +000011079 m_out.branch(isOutOfBounds, rarely(outOfBoundsCase), usually(holeCase));
oliver@apple.com8c55ed02013-07-25 04:04:01 +000011080
11081 LBasicBlock innerLastNext = m_out.appendTo(outOfBoundsCase, holeCase);
11082
11083 vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +000011084 Void, m_out.operation(slowPathFunction),
oliver@apple.com8c55ed02013-07-25 04:04:01 +000011085 m_callFrame, base, index, value);
11086
11087 m_out.jump(continuation);
11088
11089 m_out.appendTo(holeCase, innerLastNext);
11090 }
11091
11092 m_out.store32(
11093 m_out.add(index, m_out.int32One),
11094 storage, m_heaps.Butterfly_publicLength);
11095
11096 m_out.jump(performStore);
11097 m_out.appendTo(performStore, lastNext);
11098 }
11099 }
11100
oliver@apple.com39478942013-07-25 04:03:18 +000011101 void buildSwitch(SwitchData* data, LType type, LValue switchValue)
11102 {
fpizlo@apple.com994d4532016-07-03 19:34:55 +000011103 ASSERT(type == pointerType() || type == Int32);
benjamin@webkit.org81ec96c2015-11-18 23:14:54 +000011104
oliver@apple.com39478942013-07-25 04:03:18 +000011105 Vector<SwitchCase> cases;
11106 for (unsigned i = 0; i < data->cases.size(); ++i) {
benjamin@webkit.org81ec96c2015-11-18 23:14:54 +000011107 SwitchCase newCase;
11108
fpizlo@apple.com994d4532016-07-03 19:34:55 +000011109 if (type == pointerType()) {
benjamin@webkit.org81ec96c2015-11-18 23:14:54 +000011110 newCase = SwitchCase(m_out.constIntPtr(data->cases[i].value.switchLookupValue(data->kind)),
11111 lowBlock(data->cases[i].target.block), Weight(data->cases[i].target.count));
fpizlo@apple.com994d4532016-07-03 19:34:55 +000011112 } else if (type == Int32) {
benjamin@webkit.org81ec96c2015-11-18 23:14:54 +000011113 newCase = SwitchCase(m_out.constInt32(data->cases[i].value.switchLookupValue(data->kind)),
11114 lowBlock(data->cases[i].target.block), Weight(data->cases[i].target.count));
11115 } else
11116 CRASH();
11117
11118 cases.append(newCase);
oliver@apple.com39478942013-07-25 04:03:18 +000011119 }
11120
fpizlo@apple.comb8377cd2014-02-20 08:00:28 +000011121 m_out.switchInstruction(
11122 switchValue, cases,
11123 lowBlock(data->fallThrough.block), Weight(data->fallThrough.count));
oliver@apple.com39478942013-07-25 04:03:18 +000011124 }
11125
fpizlo@apple.com5a3036b2015-04-29 03:34:43 +000011126 void switchString(SwitchData* data, LValue string)
11127 {
11128 bool canDoBinarySwitch = true;
11129 unsigned totalLength = 0;
11130
11131 for (DFG::SwitchCase myCase : data->cases) {
11132 StringImpl* string = myCase.value.stringImpl();
11133 if (!string->is8Bit()) {
11134 canDoBinarySwitch = false;
11135 break;
11136 }
11137 if (string->length() > Options::maximumBinaryStringSwitchCaseLength()) {
11138 canDoBinarySwitch = false;
11139 break;
11140 }
11141 totalLength += string->length();
11142 }
11143
11144 if (!canDoBinarySwitch || totalLength > Options::maximumBinaryStringSwitchTotalLength()) {
11145 switchStringSlow(data, string);
11146 return;
11147 }
11148
11149 LValue stringImpl = m_out.loadPtr(string, m_heaps.JSString_value);
11150 LValue length = m_out.load32(string, m_heaps.JSString_length);
11151
fpizlo@apple.com91331742016-03-07 02:07:28 +000011152 LBasicBlock hasImplBlock = m_out.newBlock();
11153 LBasicBlock is8BitBlock = m_out.newBlock();
11154 LBasicBlock slowBlock = m_out.newBlock();
fpizlo@apple.com5a3036b2015-04-29 03:34:43 +000011155
11156 m_out.branch(m_out.isNull(stringImpl), unsure(slowBlock), unsure(hasImplBlock));
11157
11158 LBasicBlock lastNext = m_out.appendTo(hasImplBlock, is8BitBlock);
11159
11160 m_out.branch(
11161 m_out.testIsZero32(
11162 m_out.load32(stringImpl, m_heaps.StringImpl_hashAndFlags),
11163 m_out.constInt32(StringImpl::flagIs8Bit())),
11164 unsure(slowBlock), unsure(is8BitBlock));
11165
11166 m_out.appendTo(is8BitBlock, slowBlock);
11167
11168 LValue buffer = m_out.loadPtr(stringImpl, m_heaps.StringImpl_data);
11169
11170 // FIXME: We should propagate branch weight data to the cases of this switch.
11171 // https://bugs.webkit.org/show_bug.cgi?id=144368
11172
11173 Vector<StringSwitchCase> cases;
11174 for (DFG::SwitchCase myCase : data->cases)
11175 cases.append(StringSwitchCase(myCase.value.stringImpl(), lowBlock(myCase.target.block)));
11176 std::sort(cases.begin(), cases.end());
11177 switchStringRecurse(data, buffer, length, cases, 0, 0, cases.size(), 0, false);
11178
11179 m_out.appendTo(slowBlock, lastNext);
11180 switchStringSlow(data, string);
11181 }
11182
11183 // The code for string switching is based closely on the same code in the DFG backend. While it
11184 // would be nice to reduce the amount of similar-looking code, it seems like this is one of
11185 // those algorithms where factoring out the common bits would result in more code than just
11186 // duplicating.
11187
11188 struct StringSwitchCase {
11189 StringSwitchCase() { }
11190
11191 StringSwitchCase(StringImpl* string, LBasicBlock target)
11192 : string(string)
11193 , target(target)
11194 {
11195 }
11196
11197 bool operator<(const StringSwitchCase& other) const
11198 {
11199 return stringLessThan(*string, *other.string);
11200 }
11201
11202 StringImpl* string;
11203 LBasicBlock target;
11204 };
11205
11206 struct CharacterCase {
11207 CharacterCase()
11208 : character(0)
11209 , begin(0)
11210 , end(0)
11211 {
11212 }
11213
11214 CharacterCase(LChar character, unsigned begin, unsigned end)
11215 : character(character)
11216 , begin(begin)
11217 , end(end)
11218 {
11219 }
11220
11221 bool operator<(const CharacterCase& other) const
11222 {
11223 return character < other.character;
11224 }
11225
11226 LChar character;
11227 unsigned begin;
11228 unsigned end;
11229 };
11230
11231 void switchStringRecurse(
11232 SwitchData* data, LValue buffer, LValue length, const Vector<StringSwitchCase>& cases,
11233 unsigned numChecked, unsigned begin, unsigned end, unsigned alreadyCheckedLength,
11234 unsigned checkedExactLength)
11235 {
11236 LBasicBlock fallThrough = lowBlock(data->fallThrough.block);
11237
11238 if (begin == end) {
11239 m_out.jump(fallThrough);
11240 return;
11241 }
11242
11243 unsigned minLength = cases[begin].string->length();
11244 unsigned commonChars = minLength;
11245 bool allLengthsEqual = true;
11246 for (unsigned i = begin + 1; i < end; ++i) {
11247 unsigned myCommonChars = numChecked;
11248 unsigned limit = std::min(cases[begin].string->length(), cases[i].string->length());
11249 for (unsigned j = numChecked; j < limit; ++j) {
11250 if (cases[begin].string->at(j) != cases[i].string->at(j))
11251 break;
11252 myCommonChars++;
11253 }
11254 commonChars = std::min(commonChars, myCommonChars);
11255 if (minLength != cases[i].string->length())
11256 allLengthsEqual = false;
11257 minLength = std::min(minLength, cases[i].string->length());
11258 }
11259
11260 if (checkedExactLength) {
11261 DFG_ASSERT(m_graph, m_node, alreadyCheckedLength == minLength);
11262 DFG_ASSERT(m_graph, m_node, allLengthsEqual);
11263 }
11264
11265 DFG_ASSERT(m_graph, m_node, minLength >= commonChars);
11266
11267 if (!allLengthsEqual && alreadyCheckedLength < minLength)
11268 m_out.check(m_out.below(length, m_out.constInt32(minLength)), unsure(fallThrough));
11269 if (allLengthsEqual && (alreadyCheckedLength < minLength || !checkedExactLength))
11270 m_out.check(m_out.notEqual(length, m_out.constInt32(minLength)), unsure(fallThrough));
11271
11272 for (unsigned i = numChecked; i < commonChars; ++i) {
11273 m_out.check(
11274 m_out.notEqual(
benjamin@webkit.org2e864d22015-11-17 06:20:21 +000011275 m_out.load8ZeroExt32(buffer, m_heaps.characters8[i]),
11276 m_out.constInt32(static_cast<uint16_t>(cases[begin].string->at(i)))),
fpizlo@apple.com5a3036b2015-04-29 03:34:43 +000011277 unsure(fallThrough));
11278 }
11279
11280 if (minLength == commonChars) {
11281 // This is the case where one of the cases is a prefix of all of the other cases.
11282 // We've already checked that the input string is a prefix of all of the cases,
11283 // so we just check length to jump to that case.
11284
11285 DFG_ASSERT(m_graph, m_node, cases[begin].string->length() == commonChars);
11286 for (unsigned i = begin + 1; i < end; ++i)
11287 DFG_ASSERT(m_graph, m_node, cases[i].string->length() > commonChars);
11288
11289 if (allLengthsEqual) {
11290 DFG_ASSERT(m_graph, m_node, end == begin + 1);
11291 m_out.jump(cases[begin].target);
11292 return;
11293 }
11294
11295 m_out.check(
11296 m_out.equal(length, m_out.constInt32(commonChars)),
11297 unsure(cases[begin].target));
11298
11299 // We've checked if the length is >= minLength, and then we checked if the length is
11300 // == commonChars. We get to this point if it is >= minLength but not == commonChars.
11301 // Hence we know that it now must be > minLength, i.e. that it's >= minLength + 1.
11302 switchStringRecurse(
11303 data, buffer, length, cases, commonChars, begin + 1, end, minLength + 1, false);
11304 return;
11305 }
11306
11307 // At this point we know that the string is longer than commonChars, and we've only verified
11308 // commonChars. Use a binary switch on the next unchecked character, i.e.
11309 // string[commonChars].
11310
11311 DFG_ASSERT(m_graph, m_node, end >= begin + 2);
11312
benjamin@webkit.org2e864d22015-11-17 06:20:21 +000011313 LValue uncheckedChar = m_out.load8ZeroExt32(buffer, m_heaps.characters8[commonChars]);
fpizlo@apple.com5a3036b2015-04-29 03:34:43 +000011314
11315 Vector<CharacterCase> characterCases;
11316 CharacterCase currentCase(cases[begin].string->at(commonChars), begin, begin + 1);
11317 for (unsigned i = begin + 1; i < end; ++i) {
11318 LChar currentChar = cases[i].string->at(commonChars);
11319 if (currentChar != currentCase.character) {
11320 currentCase.end = i;
11321 characterCases.append(currentCase);
11322 currentCase = CharacterCase(currentChar, i, i + 1);
11323 } else
11324 currentCase.end = i + 1;
11325 }
11326 characterCases.append(currentCase);
11327
11328 Vector<LBasicBlock> characterBlocks;
fpizlo@apple.com91331742016-03-07 02:07:28 +000011329 for (unsigned i = characterCases.size(); i--;)
11330 characterBlocks.append(m_out.newBlock());
fpizlo@apple.com5a3036b2015-04-29 03:34:43 +000011331
11332 Vector<SwitchCase> switchCases;
11333 for (unsigned i = 0; i < characterCases.size(); ++i) {
fpizlo@apple.comb1e1c2d2015-05-05 20:42:44 +000011334 if (i)
11335 DFG_ASSERT(m_graph, m_node, characterCases[i - 1].character < characterCases[i].character);
fpizlo@apple.com5a3036b2015-04-29 03:34:43 +000011336 switchCases.append(SwitchCase(
benjamin@webkit.org2e864d22015-11-17 06:20:21 +000011337 m_out.constInt32(characterCases[i].character), characterBlocks[i], Weight()));
fpizlo@apple.com5a3036b2015-04-29 03:34:43 +000011338 }
11339 m_out.switchInstruction(uncheckedChar, switchCases, fallThrough, Weight());
11340
11341 LBasicBlock lastNext = m_out.m_nextBlock;
11342 characterBlocks.append(lastNext); // Makes it convenient to set nextBlock.
11343 for (unsigned i = 0; i < characterCases.size(); ++i) {
11344 m_out.appendTo(characterBlocks[i], characterBlocks[i + 1]);
11345 switchStringRecurse(
11346 data, buffer, length, cases, commonChars + 1,
11347 characterCases[i].begin, characterCases[i].end, minLength, allLengthsEqual);
11348 }
11349
11350 DFG_ASSERT(m_graph, m_node, m_out.m_nextBlock == lastNext);
11351 }
11352
11353 void switchStringSlow(SwitchData* data, LValue string)
11354 {
11355 // FIXME: We ought to be able to use computed gotos here. We would save the labels of the
11356 // blocks we want to jump to, and then request their addresses after compilation completes.
11357 // https://bugs.webkit.org/show_bug.cgi?id=144369
11358
11359 LValue branchOffset = vmCall(
fpizlo@apple.com994d4532016-07-03 19:34:55 +000011360 Int32, m_out.operation(operationSwitchStringAndGetBranchOffset),
fpizlo@apple.com5a3036b2015-04-29 03:34:43 +000011361 m_callFrame, m_out.constIntPtr(data->switchTableIndex), string);
11362
11363 StringJumpTable& table = codeBlock()->stringSwitchJumpTable(data->switchTableIndex);
11364
11365 Vector<SwitchCase> cases;
fpizlo@apple.comb1e1c2d2015-05-05 20:42:44 +000011366 std::unordered_set<int32_t> alreadyHandled; // These may be negative, or zero, or probably other stuff, too. We don't want to mess with HashSet's corner cases and we don't really care about throughput here.
fpizlo@apple.com5a3036b2015-04-29 03:34:43 +000011367 for (unsigned i = 0; i < data->cases.size(); ++i) {
fpizlo@apple.comb1e1c2d2015-05-05 20:42:44 +000011368 // FIXME: The fact that we're using the bytecode's switch table means that the
11369 // following DFG IR transformation would be invalid.
11370 //
11371 // Original code:
11372 // switch (v) {
11373 // case "foo":
11374 // case "bar":
11375 // things();
11376 // break;
11377 // default:
11378 // break;
11379 // }
11380 //
11381 // New code:
11382 // switch (v) {
11383 // case "foo":
11384 // instrumentFoo();
11385 // goto _things;
11386 // case "bar":
11387 // instrumentBar();
11388 // _things:
11389 // things();
11390 // break;
11391 // default:
11392 // break;
11393 // }
11394 //
11395 // Luckily, we don't currently do any such transformation. But it's kind of silly that
11396 // this is an issue.
11397 // https://bugs.webkit.org/show_bug.cgi?id=144635
11398
fpizlo@apple.com5a3036b2015-04-29 03:34:43 +000011399 DFG::SwitchCase myCase = data->cases[i];
11400 StringJumpTable::StringOffsetTable::iterator iter =
11401 table.offsetTable.find(myCase.value.stringImpl());
11402 DFG_ASSERT(m_graph, m_node, iter != table.offsetTable.end());
11403
fpizlo@apple.comb1e1c2d2015-05-05 20:42:44 +000011404 if (!alreadyHandled.insert(iter->value.branchOffset).second)
11405 continue;
11406
fpizlo@apple.com5a3036b2015-04-29 03:34:43 +000011407 cases.append(SwitchCase(
11408 m_out.constInt32(iter->value.branchOffset),
11409 lowBlock(myCase.target.block), Weight(myCase.target.count)));
11410 }
11411
11412 m_out.switchInstruction(
11413 branchOffset, cases, lowBlock(data->fallThrough.block),
11414 Weight(data->fallThrough.count));
11415 }
11416
fpizlo@apple.comb8823d52015-05-03 00:15:27 +000011417 // Calls the functor at the point of code generation where we know what the result type is.
11418 // You can emit whatever code you like at that point. Expects you to terminate the basic block.
11419 // When buildTypeOf() returns, it will have terminated all basic blocks that it created. So, if
11420 // you aren't using this as the terminator of a high-level block, you should create your own
11421 // contination and set it as the nextBlock (m_out.insertNewBlocksBefore(continuation)) before
11422 // calling this. For example:
11423 //
fpizlo@apple.com91331742016-03-07 02:07:28 +000011424 // LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.comb8823d52015-05-03 00:15:27 +000011425 // LBasicBlock lastNext = m_out.insertNewBlocksBefore(continuation);
11426 // buildTypeOf(
11427 // child, value,
11428 // [&] (TypeofType type) {
11429 // do things;
11430 // m_out.jump(continuation);
11431 // });
11432 // m_out.appendTo(continuation, lastNext);
11433 template<typename Functor>
11434 void buildTypeOf(Edge child, LValue value, const Functor& functor)
11435 {
11436 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
11437
11438 // Implements the following branching structure:
11439 //
11440 // if (is cell) {
11441 // if (is object) {
11442 // if (is function) {
11443 // return function;
11444 // } else if (doesn't have call trap and doesn't masquerade as undefined) {
11445 // return object
11446 // } else {
11447 // return slowPath();
11448 // }
11449 // } else if (is string) {
11450 // return string
11451 // } else {
11452 // return symbol
11453 // }
11454 // } else if (is number) {
11455 // return number
11456 // } else if (is null) {
11457 // return object
11458 // } else if (is boolean) {
11459 // return boolean
11460 // } else {
11461 // return undefined
11462 // }
11463
fpizlo@apple.com91331742016-03-07 02:07:28 +000011464 LBasicBlock cellCase = m_out.newBlock();
11465 LBasicBlock objectCase = m_out.newBlock();
11466 LBasicBlock functionCase = m_out.newBlock();
11467 LBasicBlock notFunctionCase = m_out.newBlock();
11468 LBasicBlock reallyObjectCase = m_out.newBlock();
11469 LBasicBlock slowPath = m_out.newBlock();
11470 LBasicBlock unreachable = m_out.newBlock();
11471 LBasicBlock notObjectCase = m_out.newBlock();
11472 LBasicBlock stringCase = m_out.newBlock();
11473 LBasicBlock symbolCase = m_out.newBlock();
11474 LBasicBlock notCellCase = m_out.newBlock();
11475 LBasicBlock numberCase = m_out.newBlock();
11476 LBasicBlock notNumberCase = m_out.newBlock();
11477 LBasicBlock notNullCase = m_out.newBlock();
11478 LBasicBlock booleanCase = m_out.newBlock();
11479 LBasicBlock undefinedCase = m_out.newBlock();
fpizlo@apple.comb8823d52015-05-03 00:15:27 +000011480
11481 m_out.branch(isCell(value, provenType(child)), unsure(cellCase), unsure(notCellCase));
11482
11483 LBasicBlock lastNext = m_out.appendTo(cellCase, objectCase);
11484 m_out.branch(isObject(value, provenType(child)), unsure(objectCase), unsure(notObjectCase));
11485
11486 m_out.appendTo(objectCase, functionCase);
11487 m_out.branch(
11488 isFunction(value, provenType(child) & SpecObject),
11489 unsure(functionCase), unsure(notFunctionCase));
11490
11491 m_out.appendTo(functionCase, notFunctionCase);
11492 functor(TypeofType::Function);
11493
11494 m_out.appendTo(notFunctionCase, reallyObjectCase);
11495 m_out.branch(
11496 isExoticForTypeof(value, provenType(child) & (SpecObject - SpecFunction)),
11497 rarely(slowPath), usually(reallyObjectCase));
11498
11499 m_out.appendTo(reallyObjectCase, slowPath);
11500 functor(TypeofType::Object);
11501
11502 m_out.appendTo(slowPath, unreachable);
fpizlo@apple.com6e697962015-10-12 17:56:26 +000011503 LValue result = lazySlowPath(
11504 [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
11505 return createLazyCallGenerator(
11506 operationTypeOfObjectAsTypeofType, locations[0].directGPR(),
11507 CCallHelpers::TrustedImmPtr(globalObject), locations[1].directGPR());
11508 }, value);
fpizlo@apple.comb8823d52015-05-03 00:15:27 +000011509 Vector<SwitchCase, 3> cases;
11510 cases.append(SwitchCase(m_out.constInt32(static_cast<int32_t>(TypeofType::Undefined)), undefinedCase));
11511 cases.append(SwitchCase(m_out.constInt32(static_cast<int32_t>(TypeofType::Object)), reallyObjectCase));
11512 cases.append(SwitchCase(m_out.constInt32(static_cast<int32_t>(TypeofType::Function)), functionCase));
fpizlo@apple.com6e697962015-10-12 17:56:26 +000011513 m_out.switchInstruction(m_out.castToInt32(result), cases, unreachable, Weight());
fpizlo@apple.comb8823d52015-05-03 00:15:27 +000011514
11515 m_out.appendTo(unreachable, notObjectCase);
11516 m_out.unreachable();
11517
11518 m_out.appendTo(notObjectCase, stringCase);
11519 m_out.branch(
11520 isString(value, provenType(child) & (SpecCell - SpecObject)),
11521 unsure(stringCase), unsure(symbolCase));
11522
11523 m_out.appendTo(stringCase, symbolCase);
11524 functor(TypeofType::String);
11525
11526 m_out.appendTo(symbolCase, notCellCase);
11527 functor(TypeofType::Symbol);
11528
11529 m_out.appendTo(notCellCase, numberCase);
11530 m_out.branch(
11531 isNumber(value, provenType(child) & ~SpecCell),
11532 unsure(numberCase), unsure(notNumberCase));
11533
11534 m_out.appendTo(numberCase, notNumberCase);
11535 functor(TypeofType::Number);
11536
11537 m_out.appendTo(notNumberCase, notNullCase);
11538 LValue isNull;
11539 if (provenType(child) & SpecOther)
11540 isNull = m_out.equal(value, m_out.constInt64(ValueNull));
11541 else
11542 isNull = m_out.booleanFalse;
11543 m_out.branch(isNull, unsure(reallyObjectCase), unsure(notNullCase));
11544
11545 m_out.appendTo(notNullCase, booleanCase);
11546 m_out.branch(
11547 isBoolean(value, provenType(child) & ~(SpecCell | SpecFullNumber)),
11548 unsure(booleanCase), unsure(undefinedCase));
11549
11550 m_out.appendTo(booleanCase, undefinedCase);
11551 functor(TypeofType::Boolean);
11552
11553 m_out.appendTo(undefinedCase, lastNext);
11554 functor(TypeofType::Undefined);
11555 }
11556
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +000011557 LValue doubleToInt32(LValue doubleValue, double low, double high, bool isSigned = true)
11558 {
fpizlo@apple.com91331742016-03-07 02:07:28 +000011559 LBasicBlock greatEnough = m_out.newBlock();
11560 LBasicBlock withinRange = m_out.newBlock();
11561 LBasicBlock slowPath = m_out.newBlock();
11562 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +000011563
11564 Vector<ValueFromBlock, 2> results;
11565
11566 m_out.branch(
fpizlo@apple.com1077d6f2013-11-03 00:29:14 +000011567 m_out.doubleGreaterThanOrEqual(doubleValue, m_out.constDouble(low)),
fpizlo@apple.com975ae502014-02-19 22:29:43 +000011568 unsure(greatEnough), unsure(slowPath));
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +000011569
11570 LBasicBlock lastNext = m_out.appendTo(greatEnough, withinRange);
11571 m_out.branch(
fpizlo@apple.com1077d6f2013-11-03 00:29:14 +000011572 m_out.doubleLessThanOrEqual(doubleValue, m_out.constDouble(high)),
fpizlo@apple.com975ae502014-02-19 22:29:43 +000011573 unsure(withinRange), unsure(slowPath));
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +000011574
11575 m_out.appendTo(withinRange, slowPath);
11576 LValue fastResult;
11577 if (isSigned)
fpizlo@apple.comdae23fb2015-12-21 20:54:51 +000011578 fastResult = m_out.doubleToInt(doubleValue);
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +000011579 else
fpizlo@apple.comdae23fb2015-12-21 20:54:51 +000011580 fastResult = m_out.doubleToUInt(doubleValue);
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +000011581 results.append(m_out.anchor(fastResult));
11582 m_out.jump(continuation);
11583
11584 m_out.appendTo(slowPath, continuation);
fpizlo@apple.com994d4532016-07-03 19:34:55 +000011585 results.append(m_out.anchor(m_out.call(Int32, m_out.operation(operationToInt32), doubleValue)));
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +000011586 m_out.jump(continuation);
11587
11588 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +000011589 return m_out.phi(Int32, results);
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +000011590 }
11591
11592 LValue doubleToInt32(LValue doubleValue)
11593 {
fpizlo@apple.com9ba2f352013-12-06 01:47:19 +000011594 if (Output::hasSensibleDoubleToInt())
11595 return sensibleDoubleToInt32(doubleValue);
11596
fpizlo@apple.come9b0dd22013-09-08 04:08:01 +000011597 double limit = pow(2, 31) - 1;
11598 return doubleToInt32(doubleValue, -limit, limit);
11599 }
11600
fpizlo@apple.com9ba2f352013-12-06 01:47:19 +000011601 LValue sensibleDoubleToInt32(LValue doubleValue)
11602 {
fpizlo@apple.com91331742016-03-07 02:07:28 +000011603 LBasicBlock slowPath = m_out.newBlock();
11604 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com373ed6b2015-12-15 04:52:55 +000011605
fpizlo@apple.comdae23fb2015-12-21 20:54:51 +000011606 LValue fastResultValue = m_out.doubleToInt(doubleValue);
fpizlo@apple.com373ed6b2015-12-15 04:52:55 +000011607 ValueFromBlock fastResult = m_out.anchor(fastResultValue);
fpizlo@apple.com9ba2f352013-12-06 01:47:19 +000011608 m_out.branch(
fpizlo@apple.com373ed6b2015-12-15 04:52:55 +000011609 m_out.equal(fastResultValue, m_out.constInt32(0x80000000)),
fpizlo@apple.com975ae502014-02-19 22:29:43 +000011610 rarely(slowPath), usually(continuation));
fpizlo@apple.com9ba2f352013-12-06 01:47:19 +000011611
11612 LBasicBlock lastNext = m_out.appendTo(slowPath, continuation);
11613 ValueFromBlock slowResult = m_out.anchor(
fpizlo@apple.com994d4532016-07-03 19:34:55 +000011614 m_out.call(Int32, m_out.operation(operationToInt32), doubleValue));
fpizlo@apple.com9ba2f352013-12-06 01:47:19 +000011615 m_out.jump(continuation);
11616
11617 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +000011618 return m_out.phi(Int32, fastResult, slowResult);
fpizlo@apple.com9ba2f352013-12-06 01:47:19 +000011619 }
fpizlo@apple.com6e697962015-10-12 17:56:26 +000011620
11621 // This is a mechanism for creating a code generator that fills in a gap in the code using our
11622 // own MacroAssembler. This is useful for slow paths that involve a lot of code and we don't want
fpizlo@apple.com3ce6ab62016-02-18 16:40:25 +000011623 // to pay the price of B3 optimizing it. A lazy slow path will only be generated if it actually
fpizlo@apple.com6e697962015-10-12 17:56:26 +000011624 // executes. On the other hand, a lazy slow path always incurs the cost of two additional jumps.
fpizlo@apple.com3ce6ab62016-02-18 16:40:25 +000011625 // Also, the lazy slow path's register allocation state is slaved to whatever B3 did, so you
fpizlo@apple.com6e697962015-10-12 17:56:26 +000011626 // have to use a ScratchRegisterAllocator to try to use some unused registers and you may have
11627 // to spill to top of stack if there aren't enough registers available.
11628 //
11629 // Lazy slow paths involve three different stages of execution. Each stage has unique
11630 // capabilities and knowledge. The stages are:
11631 //
fpizlo@apple.com3ce6ab62016-02-18 16:40:25 +000011632 // 1) DFG->B3 lowering, i.e. code that runs in this phase. Lowering is the last time you will
fpizlo@apple.com6e697962015-10-12 17:56:26 +000011633 // have access to LValues. If there is an LValue that needs to be fed as input to a lazy slow
11634 // path, then you must pass it as an argument here (as one of the varargs arguments after the
11635 // functor). But, lowering doesn't know which registers will be used for those LValues. Hence
11636 // you pass a lambda to lazySlowPath() and that lambda will run during stage (2):
11637 //
11638 // 2) FTLCompile.cpp's fixFunctionBasedOnStackMaps. This code is the only stage at which we know
fpizlo@apple.com3ce6ab62016-02-18 16:40:25 +000011639 // the mapping from arguments passed to this method in (1) and the registers that B3
fpizlo@apple.com6e697962015-10-12 17:56:26 +000011640 // selected for those arguments. You don't actually want to generate any code here, since then
11641 // the slow path wouldn't actually be lazily generated. Instead, you want to save the
11642 // registers being used for the arguments and defer code generation to stage (3) by creating
11643 // and returning a LazySlowPath::Generator:
11644 //
11645 // 3) LazySlowPath's generate() method. This code runs in response to the lazy slow path
11646 // executing for the first time. It will call the generator you created in stage (2).
11647 //
11648 // Note that each time you invoke stage (1), stage (2) may be invoked zero, one, or many times.
fpizlo@apple.com3ce6ab62016-02-18 16:40:25 +000011649 // Stage (2) will usually be invoked once for stage (1). But, B3 may kill the code, in which
11650 // case stage (2) won't run. B3 may duplicate the code (for example via tail duplication),
fpizlo@apple.com6e697962015-10-12 17:56:26 +000011651 // leading to many calls to your stage (2) lambda. Stage (3) may be called zero or once for each
11652 // stage (2). It will be called zero times if the slow path never runs. This is what you hope for
11653 // whenever you use the lazySlowPath() mechanism.
11654 //
11655 // A typical use of lazySlowPath() will look like the example below, which just creates a slow
11656 // path that adds some value to the input and returns it.
11657 //
11658 // // Stage (1) is here. This is your last chance to figure out which LValues to use as inputs.
11659 // // Notice how we pass "input" as an argument to lazySlowPath().
11660 // LValue input = ...;
11661 // int addend = ...;
11662 // LValue output = lazySlowPath(
11663 // [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
11664 // // Stage (2) is here. This is your last chance to figure out which registers are used
11665 // // for which values. Location zero is always the return value. You can ignore it if
11666 // // you don't want to return anything. Location 1 is the register for the first
11667 // // argument to the lazySlowPath(), i.e. "input". Note that the Location object could
11668 // // also hold an FPR, if you are passing a double.
11669 // GPRReg outputGPR = locations[0].directGPR();
11670 // GPRReg inputGPR = locations[1].directGPR();
11671 // return LazySlowPath::createGenerator(
11672 // [=] (CCallHelpers& jit, LazySlowPath::GenerationParams& params) {
11673 // // Stage (3) is here. This is when you generate code. You have access to the
11674 // // registers you collected in stage (2) because this lambda closes over those
11675 // // variables (outputGPR and inputGPR). You also have access to whatever extra
11676 // // data you collected in stage (1), such as the addend in this case.
11677 // jit.add32(TrustedImm32(addend), inputGPR, outputGPR);
11678 // // You have to end by jumping to done. There is nothing to fall through to.
11679 // // You can also jump to the exception handler (see LazySlowPath.h for more
11680 // // info). Note that currently you cannot OSR exit.
11681 // params.doneJumps.append(jit.jump());
11682 // });
11683 // },
11684 // input);
11685 //
fpizlo@apple.com6da135f2015-10-12 18:11:26 +000011686 // You can basically pass as many inputs as you like, either using this varargs form, or by
11687 // passing a Vector of LValues.
11688 //
fpizlo@apple.com6e697962015-10-12 17:56:26 +000011689 // Note that if your slow path is only doing a call, you can use the createLazyCallGenerator()
11690 // helper. For example:
11691 //
11692 // LValue input = ...;
11693 // LValue output = lazySlowPath(
11694 // [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
11695 // return createLazyCallGenerator(
11696 // operationDoThings, locations[0].directGPR(), locations[1].directGPR());
fpizlo@apple.com6da135f2015-10-12 18:11:26 +000011697 // }, input);
fpizlo@apple.com6e697962015-10-12 17:56:26 +000011698 //
11699 // Finally, note that all of the lambdas - both the stage (2) lambda and the stage (3) lambda -
11700 // run after the function that created them returns. Hence, you should not use by-reference
11701 // capture (i.e. [&]) in any of these lambdas.
11702 template<typename Functor, typename... ArgumentTypes>
fpizlo@apple.com9a175952016-09-28 21:55:53 +000011703 PatchpointValue* lazySlowPath(const Functor& functor, ArgumentTypes... arguments)
fpizlo@apple.com6e697962015-10-12 17:56:26 +000011704 {
11705 return lazySlowPath(functor, Vector<LValue>{ arguments... });
11706 }
11707
11708 template<typename Functor>
fpizlo@apple.com9a175952016-09-28 21:55:53 +000011709 PatchpointValue* lazySlowPath(const Functor& functor, const Vector<LValue>& userArguments)
fpizlo@apple.com6e697962015-10-12 17:56:26 +000011710 {
fpizlo@apple.com48810522015-12-01 04:43:28 +000011711 CodeOrigin origin = m_node->origin.semantic;
11712
fpizlo@apple.com18b5a352016-01-08 01:52:31 +000011713 PatchpointValue* result = m_out.patchpoint(B3::Int64);
fpizlo@apple.com602b8112015-11-19 21:00:53 +000011714 for (LValue arg : userArguments)
fpizlo@apple.com48810522015-12-01 04:43:28 +000011715 result->append(ConstrainedValue(arg, B3::ValueRep::SomeRegister));
11716
fpizlo@apple.com18b5a352016-01-08 01:52:31 +000011717 RefPtr<PatchpointExceptionHandle> exceptionHandle =
11718 preparePatchpointForExceptions(result);
fpizlo@apple.com48810522015-12-01 04:43:28 +000011719
11720 result->clobber(RegisterSet::macroScratchRegisters());
11721 State* state = &m_ftlState;
11722
fpizlo@apple.com602b8112015-11-19 21:00:53 +000011723 result->setGenerator(
fpizlo@apple.com48810522015-12-01 04:43:28 +000011724 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
11725 Vector<Location> locations;
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +000011726 for (const B3::ValueRep& rep : params)
fpizlo@apple.com48810522015-12-01 04:43:28 +000011727 locations.append(Location::forValueRep(rep));
11728
11729 RefPtr<LazySlowPath::Generator> generator = functor(locations);
11730
11731 CCallHelpers::PatchableJump patchableJump = jit.patchableJump();
11732 CCallHelpers::Label done = jit.label();
11733
fpizlo@apple.com86cbf132015-12-28 22:46:51 +000011734 RegisterSet usedRegisters = params.unavailableRegisters();
fpizlo@apple.com48810522015-12-01 04:43:28 +000011735
fpizlo@apple.com18b5a352016-01-08 01:52:31 +000011736 RefPtr<ExceptionTarget> exceptionTarget =
11737 exceptionHandle->scheduleExitCreation(params);
11738
fpizlo@apple.com48810522015-12-01 04:43:28 +000011739 // FIXME: As part of handling exceptions, we need to create a concrete OSRExit here.
11740 // Doing so should automagically register late paths that emit exit thunks.
fpizlo@apple.com48810522015-12-01 04:43:28 +000011741
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +000011742 params.addLatePath(
11743 [=] (CCallHelpers& jit) {
11744 AllowMacroScratchRegisterUsage allowScratch(jit);
11745 patchableJump.m_jump.link(&jit);
11746 unsigned index = state->jitCode->lazySlowPaths.size();
11747 state->jitCode->lazySlowPaths.append(nullptr);
11748 jit.pushToSaveImmediateWithoutTouchingRegisters(
11749 CCallHelpers::TrustedImm32(index));
11750 CCallHelpers::Jump generatorJump = jit.jump();
fpizlo@apple.com48810522015-12-01 04:43:28 +000011751
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +000011752 // Note that so long as we're here, we don't really know if our late path
11753 // runs before or after any other late paths that we might depend on, like
11754 // the exception thunk.
fpizlo@apple.com48810522015-12-01 04:43:28 +000011755
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +000011756 RefPtr<JITCode> jitCode = state->jitCode;
11757 VM* vm = &state->graph.m_vm;
11758
11759 jit.addLinkTask(
11760 [=] (LinkBuffer& linkBuffer) {
11761 linkBuffer.link(
11762 generatorJump, CodeLocationLabel(
11763 vm->getCTIStub(
11764 lazySlowPathGenerationThunkGenerator).code()));
fpizlo@apple.com86cbf132015-12-28 22:46:51 +000011765
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +000011766 CodeLocationJump linkedPatchableJump = CodeLocationJump(
11767 linkBuffer.locationOf(patchableJump));
11768 CodeLocationLabel linkedDone = linkBuffer.locationOf(done);
fpizlo@apple.com48810522015-12-01 04:43:28 +000011769
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +000011770 CallSiteIndex callSiteIndex =
11771 jitCode->common.addUniqueCallSiteIndex(origin);
fpizlo@apple.com48810522015-12-01 04:43:28 +000011772
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +000011773 std::unique_ptr<LazySlowPath> lazySlowPath =
11774 std::make_unique<LazySlowPath>(
fpizlo@apple.com18b5a352016-01-08 01:52:31 +000011775 linkedPatchableJump, linkedDone,
11776 exceptionTarget->label(linkBuffer), usedRegisters,
11777 callSiteIndex, generator);
fpizlo@apple.com48810522015-12-01 04:43:28 +000011778
aestes@apple.com13aae082016-01-02 08:03:08 +000011779 jitCode->lazySlowPaths[index] = WTFMove(lazySlowPath);
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +000011780 });
11781 });
fpizlo@apple.com602b8112015-11-19 21:00:53 +000011782 });
11783 return result;
fpizlo@apple.com6e697962015-10-12 17:56:26 +000011784 }
fpizlo@apple.com9ba2f352013-12-06 01:47:19 +000011785
oliver@apple.comea771492013-07-25 03:58:38 +000011786 void speculate(
11787 ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition)
11788 {
sbarati@apple.com5bebda72015-11-10 07:48:54 +000011789 appendOSRExit(kind, lowValue, highValue, failCondition, m_origin);
oliver@apple.comea771492013-07-25 03:58:38 +000011790 }
11791
11792 void terminate(ExitKind kind)
11793 {
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +000011794 speculate(kind, noValue(), nullptr, m_out.booleanTrue);
fpizlo@apple.com1617af22015-02-03 00:43:25 +000011795 didAlreadyTerminate();
11796 }
11797
11798 void didAlreadyTerminate()
11799 {
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +000011800 m_state.setIsValid(false);
oliver@apple.comea771492013-07-25 03:58:38 +000011801 }
11802
oliver@apple.comea771492013-07-25 03:58:38 +000011803 void typeCheck(
11804 FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough,
mark.lam@apple.comc0f1f562016-01-22 23:30:07 +000011805 LValue failCondition, ExitKind exitKind = BadType)
oliver@apple.comea771492013-07-25 03:58:38 +000011806 {
mark.lam@apple.comc0f1f562016-01-22 23:30:07 +000011807 appendTypeCheck(lowValue, highValue, typesPassedThrough, failCondition, exitKind);
oliver@apple.comea771492013-07-25 03:58:38 +000011808 }
11809
11810 void appendTypeCheck(
11811 FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough,
mark.lam@apple.comc0f1f562016-01-22 23:30:07 +000011812 LValue failCondition, ExitKind exitKind)
oliver@apple.comea771492013-07-25 03:58:38 +000011813 {
oliver@apple.com55d32d92013-07-25 04:05:03 +000011814 if (!m_interpreter.needsTypeCheck(highValue, typesPassedThrough))
oliver@apple.comea771492013-07-25 03:58:38 +000011815 return;
11816 ASSERT(mayHaveTypeCheck(highValue.useKind()));
mark.lam@apple.comc0f1f562016-01-22 23:30:07 +000011817 appendOSRExit(exitKind, lowValue, highValue.node(), failCondition, m_origin);
oliver@apple.com55d32d92013-07-25 04:05:03 +000011818 m_interpreter.filter(highValue, typesPassedThrough);
oliver@apple.comea771492013-07-25 03:58:38 +000011819 }
11820
11821 LValue lowInt32(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
11822 {
11823 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || (edge.useKind() == Int32Use || edge.useKind() == KnownInt32Use));
11824
fpizlo@apple.com6921b292013-09-18 17:14:02 +000011825 if (edge->hasConstant()) {
fpizlo@apple.comb41e6822014-07-25 20:55:17 +000011826 JSValue value = edge->asJSValue();
fpizlo@apple.com6921b292013-09-18 17:14:02 +000011827 if (!value.isInt32()) {
11828 terminate(Uncountable);
11829 return m_out.int32Zero;
11830 }
11831 return m_out.constInt32(value.asInt32());
11832 }
11833
oliver@apple.com827d2cf2013-07-25 04:04:45 +000011834 LoweredNodeValue value = m_int32Values.get(edge.node());
11835 if (isValid(value))
11836 return value.value();
oliver@apple.comea771492013-07-25 03:58:38 +000011837
fpizlo@apple.com6921b292013-09-18 17:14:02 +000011838 value = m_strictInt52Values.get(edge.node());
11839 if (isValid(value))
11840 return strictInt52ToInt32(edge, value.value());
11841
11842 value = m_int52Values.get(edge.node());
11843 if (isValid(value))
11844 return strictInt52ToInt32(edge, int52ToStrictInt52(value.value()));
11845
oliver@apple.com827d2cf2013-07-25 04:04:45 +000011846 value = m_jsValueValues.get(edge.node());
11847 if (isValid(value)) {
11848 LValue boxedResult = value.value();
oliver@apple.comea771492013-07-25 03:58:38 +000011849 FTL_TYPE_CHECK(
mark.lam@apple.com39e9c982016-04-25 17:48:46 +000011850 jsValueValue(boxedResult), edge, SpecInt32Only, isNotInt32(boxedResult));
oliver@apple.comea771492013-07-25 03:58:38 +000011851 LValue result = unboxInt32(boxedResult);
oliver@apple.com827d2cf2013-07-25 04:04:45 +000011852 setInt32(edge.node(), result);
oliver@apple.comea771492013-07-25 03:58:38 +000011853 return result;
11854 }
11855
mark.lam@apple.com39e9c982016-04-25 17:48:46 +000011856 DFG_ASSERT(m_graph, m_node, !(provenType(edge) & SpecInt32Only));
oliver@apple.comea771492013-07-25 03:58:38 +000011857 terminate(Uncountable);
11858 return m_out.int32Zero;
11859 }
11860
fpizlo@apple.com6921b292013-09-18 17:14:02 +000011861 enum Int52Kind { StrictInt52, Int52 };
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +000011862 LValue lowInt52(Edge edge, Int52Kind kind)
fpizlo@apple.com6921b292013-09-18 17:14:02 +000011863 {
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +000011864 DFG_ASSERT(m_graph, m_node, edge.useKind() == Int52RepUse);
fpizlo@apple.com6921b292013-09-18 17:14:02 +000011865
11866 LoweredNodeValue value;
11867
11868 switch (kind) {
11869 case Int52:
11870 value = m_int52Values.get(edge.node());
11871 if (isValid(value))
11872 return value.value();
11873
11874 value = m_strictInt52Values.get(edge.node());
11875 if (isValid(value))
11876 return strictInt52ToInt52(value.value());
11877 break;
11878
11879 case StrictInt52:
11880 value = m_strictInt52Values.get(edge.node());
11881 if (isValid(value))
11882 return value.value();
11883
11884 value = m_int52Values.get(edge.node());
11885 if (isValid(value))
11886 return int52ToStrictInt52(value.value());
11887 break;
11888 }
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +000011889
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000011890 DFG_ASSERT(m_graph, m_node, !provenType(edge));
fpizlo@apple.com6921b292013-09-18 17:14:02 +000011891 terminate(Uncountable);
11892 return m_out.int64Zero;
11893 }
11894
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +000011895 LValue lowInt52(Edge edge)
fpizlo@apple.com6921b292013-09-18 17:14:02 +000011896 {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +000011897 return lowInt52(edge, Int52);
fpizlo@apple.com6921b292013-09-18 17:14:02 +000011898 }
11899
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +000011900 LValue lowStrictInt52(Edge edge)
fpizlo@apple.com6921b292013-09-18 17:14:02 +000011901 {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +000011902 return lowInt52(edge, StrictInt52);
fpizlo@apple.com6921b292013-09-18 17:14:02 +000011903 }
11904
11905 bool betterUseStrictInt52(Node* node)
11906 {
11907 return !isValid(m_int52Values.get(node));
11908 }
11909 bool betterUseStrictInt52(Edge edge)
11910 {
11911 return betterUseStrictInt52(edge.node());
11912 }
11913 template<typename T>
11914 Int52Kind bestInt52Kind(T node)
11915 {
11916 return betterUseStrictInt52(node) ? StrictInt52 : Int52;
11917 }
11918 Int52Kind opposite(Int52Kind kind)
11919 {
11920 switch (kind) {
11921 case Int52:
11922 return StrictInt52;
11923 case StrictInt52:
11924 return Int52;
11925 }
msaboff@apple.com044ba8d2015-02-18 23:52:16 +000011926 DFG_CRASH(m_graph, m_node, "Bad use kind");
llango.u-szeged@partner.samsung.comc10c9cb2014-06-27 07:28:49 +000011927 return Int52;
fpizlo@apple.com6921b292013-09-18 17:14:02 +000011928 }
11929
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +000011930 LValue lowWhicheverInt52(Edge edge, Int52Kind& kind)
fpizlo@apple.com6921b292013-09-18 17:14:02 +000011931 {
11932 kind = bestInt52Kind(edge);
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +000011933 return lowInt52(edge, kind);
fpizlo@apple.com6921b292013-09-18 17:14:02 +000011934 }
11935
oliver@apple.comea771492013-07-25 03:58:38 +000011936 LValue lowCell(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
11937 {
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +000011938 DFG_ASSERT(m_graph, m_node, mode == ManualOperandSpeculation || DFG::isCell(edge.useKind()));
oliver@apple.comea771492013-07-25 03:58:38 +000011939
fpizlo@apple.com6921b292013-09-18 17:14:02 +000011940 if (edge->op() == JSConstant) {
sbarati@apple.com239d20b2017-01-26 23:50:58 +000011941 FrozenValue* value = edge->constant();
11942 if (!value->value().isCell()) {
fpizlo@apple.com6921b292013-09-18 17:14:02 +000011943 terminate(Uncountable);
11944 return m_out.intPtrZero;
11945 }
sbarati@apple.com239d20b2017-01-26 23:50:58 +000011946 return frozenPointer(value);
fpizlo@apple.com6921b292013-09-18 17:14:02 +000011947 }
11948
oliver@apple.com827d2cf2013-07-25 04:04:45 +000011949 LoweredNodeValue value = m_jsValueValues.get(edge.node());
11950 if (isValid(value)) {
11951 LValue uncheckedValue = value.value();
oliver@apple.comea771492013-07-25 03:58:38 +000011952 FTL_TYPE_CHECK(
oliver@apple.com827d2cf2013-07-25 04:04:45 +000011953 jsValueValue(uncheckedValue), edge, SpecCell, isNotCell(uncheckedValue));
11954 return uncheckedValue;
oliver@apple.comea771492013-07-25 03:58:38 +000011955 }
11956
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000011957 DFG_ASSERT(m_graph, m_node, !(provenType(edge) & SpecCell));
oliver@apple.comea771492013-07-25 03:58:38 +000011958 terminate(Uncountable);
11959 return m_out.intPtrZero;
11960 }
11961
11962 LValue lowObject(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
11963 {
11964 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == ObjectUse);
11965
11966 LValue result = lowCell(edge, mode);
11967 speculateObject(edge, result);
11968 return result;
11969 }
fpizlo@apple.comef515142016-03-04 06:36:24 +000011970
11971 LValue lowRegExpObject(Edge edge)
11972 {
11973 LValue result = lowCell(edge);
11974 speculateRegExpObject(edge, result);
11975 return result;
11976 }
sbarati@apple.com21fc86e2016-09-06 23:22:01 +000011977
11978 LValue lowMapObject(Edge edge)
11979 {
11980 LValue result = lowCell(edge);
11981 speculateMapObject(edge, result);
11982 return result;
11983 }
11984
11985 LValue lowSetObject(Edge edge)
11986 {
11987 LValue result = lowCell(edge);
11988 speculateSetObject(edge, result);
11989 return result;
11990 }
oliver@apple.comea771492013-07-25 03:58:38 +000011991
oliver@apple.com39478942013-07-25 04:03:18 +000011992 LValue lowString(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
11993 {
fpizlo@apple.com385a33a2014-03-18 20:53:07 +000011994 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == StringUse || edge.useKind() == KnownStringUse || edge.useKind() == StringIdentUse);
oliver@apple.com39478942013-07-25 04:03:18 +000011995
11996 LValue result = lowCell(edge, mode);
11997 speculateString(edge, result);
11998 return result;
11999 }
12000
fpizlo@apple.com385a33a2014-03-18 20:53:07 +000012001 LValue lowStringIdent(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
12002 {
12003 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == StringIdentUse);
12004
12005 LValue string = lowString(edge, mode);
12006 LValue stringImpl = m_out.loadPtr(string, m_heaps.JSString_value);
12007 speculateStringIdent(edge, string, stringImpl);
12008 return stringImpl;
12009 }
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +000012010
12011 LValue lowSymbol(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
12012 {
12013 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == SymbolUse);
12014
12015 LValue result = lowCell(edge, mode);
12016 speculateSymbol(edge, result);
12017 return result;
12018 }
fpizlo@apple.comcef76b22016-07-21 06:23:10 +000012019
oliver@apple.com410b5412013-07-25 03:59:47 +000012020 LValue lowNonNullObject(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
12021 {
12022 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == ObjectUse);
12023
12024 LValue result = lowCell(edge, mode);
12025 speculateNonNullObject(edge, result);
12026 return result;
12027 }
12028
oliver@apple.comea771492013-07-25 03:58:38 +000012029 LValue lowBoolean(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
12030 {
fpizlo@apple.com7289af32015-08-21 03:59:33 +000012031 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == BooleanUse || edge.useKind() == KnownBooleanUse);
oliver@apple.comea771492013-07-25 03:58:38 +000012032
fpizlo@apple.com6921b292013-09-18 17:14:02 +000012033 if (edge->hasConstant()) {
fpizlo@apple.comb41e6822014-07-25 20:55:17 +000012034 JSValue value = edge->asJSValue();
fpizlo@apple.com6921b292013-09-18 17:14:02 +000012035 if (!value.isBoolean()) {
12036 terminate(Uncountable);
12037 return m_out.booleanFalse;
12038 }
12039 return m_out.constBool(value.asBoolean());
12040 }
12041
oliver@apple.com827d2cf2013-07-25 04:04:45 +000012042 LoweredNodeValue value = m_booleanValues.get(edge.node());
12043 if (isValid(value))
12044 return value.value();
oliver@apple.comea771492013-07-25 03:58:38 +000012045
oliver@apple.com827d2cf2013-07-25 04:04:45 +000012046 value = m_jsValueValues.get(edge.node());
12047 if (isValid(value)) {
12048 LValue unboxedResult = value.value();
oliver@apple.comea771492013-07-25 03:58:38 +000012049 FTL_TYPE_CHECK(
12050 jsValueValue(unboxedResult), edge, SpecBoolean, isNotBoolean(unboxedResult));
12051 LValue result = unboxBoolean(unboxedResult);
oliver@apple.com827d2cf2013-07-25 04:04:45 +000012052 setBoolean(edge.node(), result);
oliver@apple.comea771492013-07-25 03:58:38 +000012053 return result;
12054 }
12055
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012056 DFG_ASSERT(m_graph, m_node, !(provenType(edge) & SpecBoolean));
oliver@apple.comea771492013-07-25 03:58:38 +000012057 terminate(Uncountable);
12058 return m_out.booleanFalse;
12059 }
12060
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +000012061 LValue lowDouble(Edge edge)
oliver@apple.com32295c12013-07-25 03:59:06 +000012062 {
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +000012063 DFG_ASSERT(m_graph, m_node, isDouble(edge.useKind()));
fpizlo@apple.com6921b292013-09-18 17:14:02 +000012064
oliver@apple.com827d2cf2013-07-25 04:04:45 +000012065 LoweredNodeValue value = m_doubleValues.get(edge.node());
12066 if (isValid(value))
12067 return value.value();
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012068 DFG_ASSERT(m_graph, m_node, !provenType(edge));
oliver@apple.com32295c12013-07-25 03:59:06 +000012069 terminate(Uncountable);
12070 return m_out.doubleZero;
12071 }
12072
oliver@apple.comea771492013-07-25 03:58:38 +000012073 LValue lowJSValue(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
12074 {
fpizlo@apple.coma398a562014-08-06 21:32:55 +000012075 DFG_ASSERT(m_graph, m_node, mode == ManualOperandSpeculation || edge.useKind() == UntypedUse);
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +000012076 DFG_ASSERT(m_graph, m_node, !isDouble(edge.useKind()));
12077 DFG_ASSERT(m_graph, m_node, edge.useKind() != Int52RepUse);
oliver@apple.comea771492013-07-25 03:58:38 +000012078
fpizlo@apple.com6921b292013-09-18 17:14:02 +000012079 if (edge->hasConstant())
fpizlo@apple.comb41e6822014-07-25 20:55:17 +000012080 return m_out.constInt64(JSValue::encode(edge->asJSValue()));
12081
oliver@apple.com827d2cf2013-07-25 04:04:45 +000012082 LoweredNodeValue value = m_jsValueValues.get(edge.node());
12083 if (isValid(value))
12084 return value.value();
oliver@apple.comea771492013-07-25 03:58:38 +000012085
oliver@apple.com827d2cf2013-07-25 04:04:45 +000012086 value = m_int32Values.get(edge.node());
12087 if (isValid(value)) {
12088 LValue result = boxInt32(value.value());
12089 setJSValue(edge.node(), result);
oliver@apple.comea771492013-07-25 03:58:38 +000012090 return result;
12091 }
12092
oliver@apple.com827d2cf2013-07-25 04:04:45 +000012093 value = m_booleanValues.get(edge.node());
12094 if (isValid(value)) {
12095 LValue result = boxBoolean(value.value());
12096 setJSValue(edge.node(), result);
oliver@apple.comea771492013-07-25 03:58:38 +000012097 return result;
12098 }
12099
msaboff@apple.com044ba8d2015-02-18 23:52:16 +000012100 DFG_CRASH(m_graph, m_node, "Value not defined");
oliver@apple.comea771492013-07-25 03:58:38 +000012101 return 0;
12102 }
12103
12104 LValue lowStorage(Edge edge)
12105 {
oliver@apple.com827d2cf2013-07-25 04:04:45 +000012106 LoweredNodeValue value = m_storageValues.get(edge.node());
12107 if (isValid(value))
12108 return value.value();
oliver@apple.comea771492013-07-25 03:58:38 +000012109
12110 LValue result = lowCell(edge);
oliver@apple.com827d2cf2013-07-25 04:04:45 +000012111 setStorage(edge.node(), result);
oliver@apple.comea771492013-07-25 03:58:38 +000012112 return result;
12113 }
sbarati@apple.com21fc86e2016-09-06 23:22:01 +000012114
12115 LValue lowMapBucket(Edge edge)
12116 {
12117 LoweredNodeValue value = m_mapBucketValues.get(edge.node());
12118 if (isValid(value))
12119 return value.value();
12120
12121 LValue result = lowCell(edge);
12122 setStorage(edge.node(), result);
12123 return result;
12124 }
oliver@apple.comea771492013-07-25 03:58:38 +000012125
fpizlo@apple.com6921b292013-09-18 17:14:02 +000012126 LValue strictInt52ToInt32(Edge edge, LValue value)
12127 {
12128 LValue result = m_out.castToInt32(value);
12129 FTL_TYPE_CHECK(
mark.lam@apple.com39e9c982016-04-25 17:48:46 +000012130 noValue(), edge, SpecInt32Only,
commit-queue@webkit.org65fa3e42015-12-04 20:27:37 +000012131 m_out.notEqual(m_out.signExt32To64(result), value));
fpizlo@apple.com6921b292013-09-18 17:14:02 +000012132 setInt32(edge.node(), result);
12133 return result;
12134 }
12135
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +000012136 LValue strictInt52ToDouble(LValue value)
fpizlo@apple.com6921b292013-09-18 17:14:02 +000012137 {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +000012138 return m_out.intToDouble(value);
fpizlo@apple.com6921b292013-09-18 17:14:02 +000012139 }
12140
12141 LValue strictInt52ToJSValue(LValue value)
12142 {
fpizlo@apple.com91331742016-03-07 02:07:28 +000012143 LBasicBlock isInt32 = m_out.newBlock();
12144 LBasicBlock isDouble = m_out.newBlock();
12145 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com6921b292013-09-18 17:14:02 +000012146
12147 Vector<ValueFromBlock, 2> results;
12148
12149 LValue int32Value = m_out.castToInt32(value);
12150 m_out.branch(
commit-queue@webkit.org65fa3e42015-12-04 20:27:37 +000012151 m_out.equal(m_out.signExt32To64(int32Value), value),
fpizlo@apple.com975ae502014-02-19 22:29:43 +000012152 unsure(isInt32), unsure(isDouble));
fpizlo@apple.com6921b292013-09-18 17:14:02 +000012153
12154 LBasicBlock lastNext = m_out.appendTo(isInt32, isDouble);
12155
12156 results.append(m_out.anchor(boxInt32(int32Value)));
12157 m_out.jump(continuation);
12158
12159 m_out.appendTo(isDouble, continuation);
12160
12161 results.append(m_out.anchor(boxDouble(m_out.intToDouble(value))));
12162 m_out.jump(continuation);
12163
12164 m_out.appendTo(continuation, lastNext);
fpizlo@apple.com994d4532016-07-03 19:34:55 +000012165 return m_out.phi(Int64, results);
fpizlo@apple.com6921b292013-09-18 17:14:02 +000012166 }
12167
fpizlo@apple.com6921b292013-09-18 17:14:02 +000012168 LValue strictInt52ToInt52(LValue value)
12169 {
12170 return m_out.shl(value, m_out.constInt64(JSValue::int52ShiftAmount));
12171 }
12172
12173 LValue int52ToStrictInt52(LValue value)
12174 {
12175 return m_out.aShr(value, m_out.constInt64(JSValue::int52ShiftAmount));
12176 }
12177
fpizlo@apple.com5b9b41b2015-05-29 20:26:37 +000012178 LValue isInt32(LValue jsValue, SpeculatedType type = SpecFullTop)
oliver@apple.comea771492013-07-25 03:58:38 +000012179 {
mark.lam@apple.com39e9c982016-04-25 17:48:46 +000012180 if (LValue proven = isProvenValue(type, SpecInt32Only))
fpizlo@apple.com5b9b41b2015-05-29 20:26:37 +000012181 return proven;
12182 return m_out.aboveOrEqual(jsValue, m_tagTypeNumber);
12183 }
12184 LValue isNotInt32(LValue jsValue, SpeculatedType type = SpecFullTop)
12185 {
mark.lam@apple.com39e9c982016-04-25 17:48:46 +000012186 if (LValue proven = isProvenValue(type, ~SpecInt32Only))
fpizlo@apple.com5b9b41b2015-05-29 20:26:37 +000012187 return proven;
oliver@apple.comea771492013-07-25 03:58:38 +000012188 return m_out.below(jsValue, m_tagTypeNumber);
12189 }
12190 LValue unboxInt32(LValue jsValue)
12191 {
12192 return m_out.castToInt32(jsValue);
12193 }
12194 LValue boxInt32(LValue value)
12195 {
fpizlo@apple.com994d4532016-07-03 19:34:55 +000012196 return m_out.add(m_out.zeroExt(value, Int64), m_tagTypeNumber);
oliver@apple.comea771492013-07-25 03:58:38 +000012197 }
12198
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012199 LValue isCellOrMisc(LValue jsValue, SpeculatedType type = SpecFullTop)
oliver@apple.com32295c12013-07-25 03:59:06 +000012200 {
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012201 if (LValue proven = isProvenValue(type, SpecCell | SpecMisc))
12202 return proven;
oliver@apple.com32295c12013-07-25 03:59:06 +000012203 return m_out.testIsZero64(jsValue, m_tagTypeNumber);
12204 }
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012205 LValue isNotCellOrMisc(LValue jsValue, SpeculatedType type = SpecFullTop)
fpizlo@apple.com40750682014-03-13 22:18:50 +000012206 {
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012207 if (LValue proven = isProvenValue(type, ~(SpecCell | SpecMisc)))
12208 return proven;
fpizlo@apple.com40750682014-03-13 22:18:50 +000012209 return m_out.testNonZero64(jsValue, m_tagTypeNumber);
12210 }
fpizlo@apple.com280ef002016-04-05 22:13:16 +000012211
oliver@apple.com32295c12013-07-25 03:59:06 +000012212 LValue unboxDouble(LValue jsValue)
12213 {
fpizlo@apple.com994d4532016-07-03 19:34:55 +000012214 return m_out.bitCast(m_out.add(jsValue, m_tagTypeNumber), Double);
oliver@apple.com32295c12013-07-25 03:59:06 +000012215 }
12216 LValue boxDouble(LValue doubleValue)
12217 {
fpizlo@apple.com994d4532016-07-03 19:34:55 +000012218 return m_out.sub(m_out.bitCast(doubleValue, Int64), m_tagTypeNumber);
oliver@apple.com32295c12013-07-25 03:59:06 +000012219 }
12220
fpizlo@apple.comf2999932014-07-15 00:41:39 +000012221 LValue jsValueToStrictInt52(Edge edge, LValue boxedValue)
12222 {
fpizlo@apple.com91331742016-03-07 02:07:28 +000012223 LBasicBlock intCase = m_out.newBlock();
12224 LBasicBlock doubleCase = m_out.newBlock();
12225 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.comf2999932014-07-15 00:41:39 +000012226
12227 LValue isNotInt32;
mark.lam@apple.com39e9c982016-04-25 17:48:46 +000012228 if (!m_interpreter.needsTypeCheck(edge, SpecInt32Only))
fpizlo@apple.comf2999932014-07-15 00:41:39 +000012229 isNotInt32 = m_out.booleanFalse;
mark.lam@apple.com39e9c982016-04-25 17:48:46 +000012230 else if (!m_interpreter.needsTypeCheck(edge, ~SpecInt32Only))
fpizlo@apple.comf2999932014-07-15 00:41:39 +000012231 isNotInt32 = m_out.booleanTrue;
12232 else
12233 isNotInt32 = this->isNotInt32(boxedValue);
12234 m_out.branch(isNotInt32, unsure(doubleCase), unsure(intCase));
12235
12236 LBasicBlock lastNext = m_out.appendTo(intCase, doubleCase);
12237
12238 ValueFromBlock intToInt52 = m_out.anchor(
commit-queue@webkit.org65fa3e42015-12-04 20:27:37 +000012239 m_out.signExt32To64(unboxInt32(boxedValue)));
fpizlo@apple.comf2999932014-07-15 00:41:39 +000012240 m_out.jump(continuation);
12241
12242 m_out.appendTo(doubleCase, continuation);
12243
12244 LValue possibleResult = m_out.call(
fpizlo@apple.com994d4532016-07-03 19:34:55 +000012245 Int64, m_out.operation(operationConvertBoxedDoubleToInt52), boxedValue);
fpizlo@apple.comf2999932014-07-15 00:41:39 +000012246 FTL_TYPE_CHECK(
mark.lam@apple.com39e9c982016-04-25 17:48:46 +000012247 jsValueValue(boxedValue), edge, SpecInt32Only | SpecAnyIntAsDouble,
fpizlo@apple.comf2999932014-07-15 00:41:39 +000012248 m_out.equal(possibleResult, m_out.constInt64(JSValue::notInt52)));
12249
12250 ValueFromBlock doubleToInt52 = m_out.anchor(possibleResult);
12251 m_out.jump(continuation);
12252
12253 m_out.appendTo(continuation, lastNext);
12254
fpizlo@apple.com994d4532016-07-03 19:34:55 +000012255 return m_out.phi(Int64, intToInt52, doubleToInt52);
fpizlo@apple.comf2999932014-07-15 00:41:39 +000012256 }
12257
12258 LValue doubleToStrictInt52(Edge edge, LValue value)
12259 {
12260 LValue possibleResult = m_out.call(
fpizlo@apple.com994d4532016-07-03 19:34:55 +000012261 Int64, m_out.operation(operationConvertDoubleToInt52), value);
mark.lam@apple.comc0f1f562016-01-22 23:30:07 +000012262 FTL_TYPE_CHECK_WITH_EXIT_KIND(Int52Overflow,
mark.lam@apple.com39e9c982016-04-25 17:48:46 +000012263 doubleValue(value), edge, SpecAnyIntAsDouble,
fpizlo@apple.comf2999932014-07-15 00:41:39 +000012264 m_out.equal(possibleResult, m_out.constInt64(JSValue::notInt52)));
12265
12266 return possibleResult;
12267 }
benjamin@webkit.orgcb584082015-05-08 00:23:32 +000012268
12269 LValue convertDoubleToInt32(LValue value, bool shouldCheckNegativeZero)
12270 {
fpizlo@apple.comdae23fb2015-12-21 20:54:51 +000012271 LValue integerValue = m_out.doubleToInt(value);
benjamin@webkit.orgcb584082015-05-08 00:23:32 +000012272 LValue integerValueConvertedToDouble = m_out.intToDouble(integerValue);
12273 LValue valueNotConvertibleToInteger = m_out.doubleNotEqualOrUnordered(value, integerValueConvertedToDouble);
basile_clement@apple.com3ed5a3a2015-09-04 18:24:38 +000012274 speculate(Overflow, FormattedValue(DataFormatDouble, value), m_node, valueNotConvertibleToInteger);
benjamin@webkit.orgcb584082015-05-08 00:23:32 +000012275
12276 if (shouldCheckNegativeZero) {
fpizlo@apple.com91331742016-03-07 02:07:28 +000012277 LBasicBlock valueIsZero = m_out.newBlock();
12278 LBasicBlock continuation = m_out.newBlock();
benjamin@webkit.orgcb584082015-05-08 00:23:32 +000012279 m_out.branch(m_out.isZero32(integerValue), unsure(valueIsZero), unsure(continuation));
12280
12281 LBasicBlock lastNext = m_out.appendTo(valueIsZero, continuation);
12282
fpizlo@apple.com994d4532016-07-03 19:34:55 +000012283 LValue doubleBitcastToInt64 = m_out.bitCast(value, Int64);
benjamin@webkit.orgcb584082015-05-08 00:23:32 +000012284 LValue signBitSet = m_out.lessThan(doubleBitcastToInt64, m_out.constInt64(0));
12285
basile_clement@apple.com3ed5a3a2015-09-04 18:24:38 +000012286 speculate(NegativeZero, FormattedValue(DataFormatDouble, value), m_node, signBitSet);
benjamin@webkit.orgcb584082015-05-08 00:23:32 +000012287 m_out.jump(continuation);
12288 m_out.appendTo(continuation, lastNext);
12289 }
12290 return integerValue;
12291 }
12292
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012293 LValue isNumber(LValue jsValue, SpeculatedType type = SpecFullTop)
fpizlo@apple.com40750682014-03-13 22:18:50 +000012294 {
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012295 if (LValue proven = isProvenValue(type, SpecFullNumber))
12296 return proven;
fpizlo@apple.com40750682014-03-13 22:18:50 +000012297 return isNotCellOrMisc(jsValue);
12298 }
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012299 LValue isNotNumber(LValue jsValue, SpeculatedType type = SpecFullTop)
fpizlo@apple.com40750682014-03-13 22:18:50 +000012300 {
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012301 if (LValue proven = isProvenValue(type, ~SpecFullNumber))
12302 return proven;
fpizlo@apple.com40750682014-03-13 22:18:50 +000012303 return isCellOrMisc(jsValue);
12304 }
12305
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012306 LValue isNotCell(LValue jsValue, SpeculatedType type = SpecFullTop)
oliver@apple.comea771492013-07-25 03:58:38 +000012307 {
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012308 if (LValue proven = isProvenValue(type, ~SpecCell))
12309 return proven;
oliver@apple.comea771492013-07-25 03:58:38 +000012310 return m_out.testNonZero64(jsValue, m_tagMask);
12311 }
12312
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012313 LValue isCell(LValue jsValue, SpeculatedType type = SpecFullTop)
fpizlo@apple.com6f2bf6c2013-12-06 20:59:16 +000012314 {
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012315 if (LValue proven = isProvenValue(type, SpecCell))
12316 return proven;
fpizlo@apple.com6f2bf6c2013-12-06 20:59:16 +000012317 return m_out.testIsZero64(jsValue, m_tagMask);
12318 }
12319
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012320 LValue isNotMisc(LValue value, SpeculatedType type = SpecFullTop)
fpizlo@apple.come079bb52014-03-05 07:41:03 +000012321 {
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012322 if (LValue proven = isProvenValue(type, ~SpecMisc))
12323 return proven;
fpizlo@apple.come079bb52014-03-05 07:41:03 +000012324 return m_out.above(value, m_out.constInt64(TagBitTypeOther | TagBitBool | TagBitUndefined));
12325 }
12326
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012327 LValue isMisc(LValue value, SpeculatedType type = SpecFullTop)
fpizlo@apple.come079bb52014-03-05 07:41:03 +000012328 {
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012329 if (LValue proven = isProvenValue(type, SpecMisc))
12330 return proven;
fpizlo@apple.com959a2c42015-12-22 21:59:59 +000012331 return m_out.logicalNot(isNotMisc(value));
fpizlo@apple.come079bb52014-03-05 07:41:03 +000012332 }
12333
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012334 LValue isNotBoolean(LValue jsValue, SpeculatedType type = SpecFullTop)
oliver@apple.comea771492013-07-25 03:58:38 +000012335 {
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012336 if (LValue proven = isProvenValue(type, ~SpecBoolean))
12337 return proven;
oliver@apple.comea771492013-07-25 03:58:38 +000012338 return m_out.testNonZero64(
12339 m_out.bitXor(jsValue, m_out.constInt64(ValueFalse)),
12340 m_out.constInt64(~1));
12341 }
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012342 LValue isBoolean(LValue jsValue, SpeculatedType type = SpecFullTop)
fpizlo@apple.com40750682014-03-13 22:18:50 +000012343 {
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012344 if (LValue proven = isProvenValue(type, SpecBoolean))
12345 return proven;
fpizlo@apple.com959a2c42015-12-22 21:59:59 +000012346 return m_out.logicalNot(isNotBoolean(jsValue));
fpizlo@apple.com40750682014-03-13 22:18:50 +000012347 }
oliver@apple.comea771492013-07-25 03:58:38 +000012348 LValue unboxBoolean(LValue jsValue)
12349 {
fpizlo@apple.com3ce6ab62016-02-18 16:40:25 +000012350 // We want to use a cast that guarantees that B3 knows that even the integer
oliver@apple.comea771492013-07-25 03:58:38 +000012351 // value is just 0 or 1. But for now we do it the dumb way.
12352 return m_out.notZero64(m_out.bitAnd(jsValue, m_out.constInt64(1)));
12353 }
12354 LValue boxBoolean(LValue value)
12355 {
12356 return m_out.select(
12357 value, m_out.constInt64(ValueTrue), m_out.constInt64(ValueFalse));
12358 }
fpizlo@apple.com76e5b2792014-02-11 20:28:59 +000012359
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012360 LValue isNotOther(LValue value, SpeculatedType type = SpecFullTop)
fpizlo@apple.com76e5b2792014-02-11 20:28:59 +000012361 {
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012362 if (LValue proven = isProvenValue(type, ~SpecOther))
12363 return proven;
fpizlo@apple.com76e5b2792014-02-11 20:28:59 +000012364 return m_out.notEqual(
12365 m_out.bitAnd(value, m_out.constInt64(~TagBitUndefined)),
12366 m_out.constInt64(ValueNull));
12367 }
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012368 LValue isOther(LValue value, SpeculatedType type = SpecFullTop)
fpizlo@apple.com76e5b2792014-02-11 20:28:59 +000012369 {
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012370 if (LValue proven = isProvenValue(type, SpecOther))
12371 return proven;
fpizlo@apple.com76e5b2792014-02-11 20:28:59 +000012372 return m_out.equal(
12373 m_out.bitAnd(value, m_out.constInt64(~TagBitUndefined)),
12374 m_out.constInt64(ValueNull));
12375 }
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012376
12377 LValue isProvenValue(SpeculatedType provenType, SpeculatedType wantedType)
12378 {
12379 if (!(provenType & ~wantedType))
12380 return m_out.booleanTrue;
12381 if (!(provenType & wantedType))
12382 return m_out.booleanFalse;
12383 return nullptr;
12384 }
oliver@apple.comea771492013-07-25 03:58:38 +000012385
12386 void speculate(Edge edge)
12387 {
12388 switch (edge.useKind()) {
12389 case UntypedUse:
12390 break;
12391 case KnownInt32Use:
msaboff@apple.com95894332014-01-29 19:18:54 +000012392 case KnownStringUse:
fpizlo@apple.com2b150e782015-08-27 23:59:57 +000012393 case KnownPrimitiveUse:
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +000012394 case DoubleRepUse:
12395 case Int52RepUse:
oliver@apple.com55d32d92013-07-25 04:05:03 +000012396 ASSERT(!m_interpreter.needsTypeCheck(edge));
oliver@apple.comea771492013-07-25 03:58:38 +000012397 break;
12398 case Int32Use:
12399 speculateInt32(edge);
12400 break;
12401 case CellUse:
12402 speculateCell(edge);
12403 break;
fpizlo@apple.com12835772015-09-21 20:49:04 +000012404 case CellOrOtherUse:
12405 speculateCellOrOther(edge);
12406 break;
oliver@apple.comea771492013-07-25 03:58:38 +000012407 case KnownCellUse:
oliver@apple.com55d32d92013-07-25 04:05:03 +000012408 ASSERT(!m_interpreter.needsTypeCheck(edge));
oliver@apple.comea771492013-07-25 03:58:38 +000012409 break;
mark.lam@apple.com39e9c982016-04-25 17:48:46 +000012410 case AnyIntUse:
12411 speculateAnyInt(edge);
fpizlo@apple.comf2999932014-07-15 00:41:39 +000012412 break;
oliver@apple.comea771492013-07-25 03:58:38 +000012413 case ObjectUse:
12414 speculateObject(edge);
12415 break;
utatane.tea@gmail.com0350d7d2016-09-16 21:17:33 +000012416 case ArrayUse:
12417 speculateArray(edge);
12418 break;
fpizlo@apple.coma398a562014-08-06 21:32:55 +000012419 case FunctionUse:
12420 speculateFunction(edge);
12421 break;
fpizlo@apple.comfa258dc2013-09-07 05:47:57 +000012422 case ObjectOrOtherUse:
12423 speculateObjectOrOther(edge);
12424 break;
fpizlo@apple.com44b4a232013-11-09 04:24:27 +000012425 case FinalObjectUse:
12426 speculateFinalObject(edge);
12427 break;
fpizlo@apple.come799b862016-03-01 21:18:42 +000012428 case RegExpObjectUse:
12429 speculateRegExpObject(edge);
12430 break;
utatane.tea@gmail.com4a748b12016-09-17 06:32:50 +000012431 case ProxyObjectUse:
12432 speculateProxyObject(edge);
12433 break;
12434 case DerivedArrayUse:
12435 speculateDerivedArray(edge);
12436 break;
sbarati@apple.com21fc86e2016-09-06 23:22:01 +000012437 case MapObjectUse:
12438 speculateMapObject(edge);
12439 break;
12440 case SetObjectUse:
12441 speculateSetObject(edge);
12442 break;
oliver@apple.com39478942013-07-25 04:03:18 +000012443 case StringUse:
12444 speculateString(edge);
12445 break;
fpizlo@apple.com91331742016-03-07 02:07:28 +000012446 case StringOrOtherUse:
12447 speculateStringOrOther(edge);
12448 break;
fpizlo@apple.com385a33a2014-03-18 20:53:07 +000012449 case StringIdentUse:
12450 speculateStringIdent(edge);
12451 break;
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +000012452 case SymbolUse:
12453 speculateSymbol(edge);
12454 break;
msaboff@apple.com95894332014-01-29 19:18:54 +000012455 case StringObjectUse:
12456 speculateStringObject(edge);
12457 break;
12458 case StringOrStringObjectUse:
12459 speculateStringOrStringObject(edge);
12460 break;
oliver@apple.com32295c12013-07-25 03:59:06 +000012461 case NumberUse:
12462 speculateNumber(edge);
12463 break;
fpizlo@apple.com318af072015-06-05 04:59:28 +000012464 case RealNumberUse:
12465 speculateRealNumber(edge);
12466 break;
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +000012467 case DoubleRepRealUse:
fpizlo@apple.com318af072015-06-05 04:59:28 +000012468 speculateDoubleRepReal(edge);
fpizlo@apple.comc6bb4a92013-09-30 20:38:46 +000012469 break;
mark.lam@apple.com39e9c982016-04-25 17:48:46 +000012470 case DoubleRepAnyIntUse:
12471 speculateDoubleRepAnyInt(edge);
fpizlo@apple.comf2999932014-07-15 00:41:39 +000012472 break;
oliver@apple.com827d2cf2013-07-25 04:04:45 +000012473 case BooleanUse:
12474 speculateBoolean(edge);
12475 break;
fpizlo@apple.com385a33a2014-03-18 20:53:07 +000012476 case NotStringVarUse:
12477 speculateNotStringVar(edge);
12478 break;
msaboff@apple.com95894332014-01-29 19:18:54 +000012479 case NotCellUse:
12480 speculateNotCell(edge);
12481 break;
fpizlo@apple.com312efcd2014-03-10 22:11:35 +000012482 case OtherUse:
12483 speculateOther(edge);
12484 break;
fpizlo@apple.come079bb52014-03-05 07:41:03 +000012485 case MiscUse:
12486 speculateMisc(edge);
12487 break;
oliver@apple.comea771492013-07-25 03:58:38 +000012488 default:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +000012489 DFG_CRASH(m_graph, m_node, "Unsupported speculation use kind");
oliver@apple.comea771492013-07-25 03:58:38 +000012490 }
12491 }
12492
12493 void speculate(Node*, Edge edge)
12494 {
12495 speculate(edge);
12496 }
12497
12498 void speculateInt32(Edge edge)
12499 {
12500 lowInt32(edge);
12501 }
12502
12503 void speculateCell(Edge edge)
12504 {
12505 lowCell(edge);
12506 }
12507
fpizlo@apple.com12835772015-09-21 20:49:04 +000012508 void speculateCellOrOther(Edge edge)
12509 {
12510 LValue value = lowJSValue(edge, ManualOperandSpeculation);
12511
fpizlo@apple.com91331742016-03-07 02:07:28 +000012512 LBasicBlock isNotCell = m_out.newBlock();
12513 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com12835772015-09-21 20:49:04 +000012514
12515 m_out.branch(isCell(value, provenType(edge)), unsure(continuation), unsure(isNotCell));
12516
12517 LBasicBlock lastNext = m_out.appendTo(isNotCell, continuation);
12518 FTL_TYPE_CHECK(jsValueValue(value), edge, SpecCell | SpecOther, isNotOther(value));
12519 m_out.jump(continuation);
12520
12521 m_out.appendTo(continuation, lastNext);
12522 }
12523
mark.lam@apple.com39e9c982016-04-25 17:48:46 +000012524 void speculateAnyInt(Edge edge)
fpizlo@apple.comf2999932014-07-15 00:41:39 +000012525 {
12526 if (!m_interpreter.needsTypeCheck(edge))
12527 return;
12528
12529 jsValueToStrictInt52(edge, lowJSValue(edge, ManualOperandSpeculation));
12530 }
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +000012531
utatane.tea@gmail.com4a748b12016-09-17 06:32:50 +000012532 LValue isCellWithType(LValue cell, JSType queriedType, SpeculatedType speculatedTypeForQuery, SpeculatedType type = SpecFullTop)
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +000012533 {
utatane.tea@gmail.com4a748b12016-09-17 06:32:50 +000012534 if (LValue proven = isProvenValue(type & SpecCell, speculatedTypeForQuery))
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +000012535 return proven;
12536 return m_out.equal(
12537 m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoType),
utatane.tea@gmail.com4a748b12016-09-17 06:32:50 +000012538 m_out.constInt32(queriedType));
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +000012539 }
keith_miller@apple.com6919bc12016-06-23 01:39:01 +000012540
12541 LValue isTypedArrayView(LValue cell, SpeculatedType type = SpecFullTop)
12542 {
12543 if (LValue proven = isProvenValue(type & SpecCell, SpecTypedArrayView))
12544 return proven;
12545 LValue jsType = m_out.sub(
12546 m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoType),
12547 m_out.constInt32(Int8ArrayType));
12548 return m_out.belowOrEqual(
12549 jsType,
12550 m_out.constInt32(Float64ArrayType - Int8ArrayType));
12551 }
fpizlo@apple.comf2999932014-07-15 00:41:39 +000012552
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012553 LValue isObject(LValue cell, SpeculatedType type = SpecFullTop)
oliver@apple.com39478942013-07-25 04:03:18 +000012554 {
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012555 if (LValue proven = isProvenValue(type & SpecCell, SpecObject))
12556 return proven;
utatane.tea@gmail.com0bfb74c2015-02-24 23:01:58 +000012557 return m_out.aboveOrEqual(
benjamin@webkit.org2e864d22015-11-17 06:20:21 +000012558 m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoType),
12559 m_out.constInt32(ObjectType));
utatane.tea@gmail.com0bfb74c2015-02-24 23:01:58 +000012560 }
12561
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012562 LValue isNotObject(LValue cell, SpeculatedType type = SpecFullTop)
utatane.tea@gmail.com0bfb74c2015-02-24 23:01:58 +000012563 {
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012564 if (LValue proven = isProvenValue(type & SpecCell, ~SpecObject))
12565 return proven;
utatane.tea@gmail.com0bfb74c2015-02-24 23:01:58 +000012566 return m_out.below(
benjamin@webkit.org2e864d22015-11-17 06:20:21 +000012567 m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoType),
12568 m_out.constInt32(ObjectType));
utatane.tea@gmail.com0bfb74c2015-02-24 23:01:58 +000012569 }
12570
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012571 LValue isNotString(LValue cell, SpeculatedType type = SpecFullTop)
utatane.tea@gmail.com0bfb74c2015-02-24 23:01:58 +000012572 {
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012573 if (LValue proven = isProvenValue(type & SpecCell, ~SpecString))
12574 return proven;
oliver@apple.com39478942013-07-25 04:03:18 +000012575 return m_out.notEqual(
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +000012576 m_out.load32(cell, m_heaps.JSCell_structureID),
12577 m_out.constInt32(vm().stringStructure->id()));
oliver@apple.com39478942013-07-25 04:03:18 +000012578 }
12579
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012580 LValue isString(LValue cell, SpeculatedType type = SpecFullTop)
oliver@apple.com39478942013-07-25 04:03:18 +000012581 {
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012582 if (LValue proven = isProvenValue(type & SpecCell, SpecString))
12583 return proven;
oliver@apple.com39478942013-07-25 04:03:18 +000012584 return m_out.equal(
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +000012585 m_out.load32(cell, m_heaps.JSCell_structureID),
12586 m_out.constInt32(vm().stringStructure->id()));
oliver@apple.com39478942013-07-25 04:03:18 +000012587 }
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +000012588
12589 LValue isNotSymbol(LValue cell, SpeculatedType type = SpecFullTop)
12590 {
12591 if (LValue proven = isProvenValue(type & SpecCell, ~SpecSymbol))
12592 return proven;
12593 return m_out.notEqual(
12594 m_out.load32(cell, m_heaps.JSCell_structureID),
12595 m_out.constInt32(vm().symbolStructure->id()));
12596 }
fpizlo@apple.comcef76b22016-07-21 06:23:10 +000012597
12598 LValue isSymbol(LValue cell, SpeculatedType type = SpecFullTop)
12599 {
12600 if (LValue proven = isProvenValue(type & SpecCell, SpecSymbol))
12601 return proven;
12602 return m_out.equal(
12603 m_out.load32(cell, m_heaps.JSCell_structureID),
12604 m_out.constInt32(vm().symbolStructure->id()));
12605 }
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +000012606
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +000012607 LValue isArrayType(LValue cell, ArrayMode arrayMode)
12608 {
12609 switch (arrayMode.type()) {
12610 case Array::Int32:
12611 case Array::Double:
12612 case Array::Contiguous: {
fpizlo@apple.com101a1682016-11-15 01:49:22 +000012613 LValue indexingType = m_out.load8ZeroExt32(cell, m_heaps.JSCell_indexingTypeAndMisc);
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +000012614
12615 switch (arrayMode.arrayClass()) {
12616 case Array::OriginalArray:
msaboff@apple.com044ba8d2015-02-18 23:52:16 +000012617 DFG_CRASH(m_graph, m_node, "Unexpected original array");
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +000012618 return 0;
12619
12620 case Array::Array:
12621 return m_out.equal(
benjamin@webkit.org2e864d22015-11-17 06:20:21 +000012622 m_out.bitAnd(indexingType, m_out.constInt32(IsArray | IndexingShapeMask)),
12623 m_out.constInt32(IsArray | arrayMode.shapeMask()));
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +000012624
fpizlo@apple.coma704e6b2013-11-06 20:32:19 +000012625 case Array::NonArray:
12626 case Array::OriginalNonArray:
12627 return m_out.equal(
benjamin@webkit.org2e864d22015-11-17 06:20:21 +000012628 m_out.bitAnd(indexingType, m_out.constInt32(IsArray | IndexingShapeMask)),
12629 m_out.constInt32(arrayMode.shapeMask()));
fpizlo@apple.coma704e6b2013-11-06 20:32:19 +000012630
12631 case Array::PossiblyArray:
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +000012632 return m_out.equal(
benjamin@webkit.org2e864d22015-11-17 06:20:21 +000012633 m_out.bitAnd(indexingType, m_out.constInt32(IndexingShapeMask)),
12634 m_out.constInt32(arrayMode.shapeMask()));
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +000012635 }
fpizlo@apple.coma704e6b2013-11-06 20:32:19 +000012636
msaboff@apple.com044ba8d2015-02-18 23:52:16 +000012637 DFG_CRASH(m_graph, m_node, "Corrupt array class");
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +000012638 }
12639
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000012640 case Array::DirectArguments:
12641 return m_out.equal(
benjamin@webkit.org2e864d22015-11-17 06:20:21 +000012642 m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoType),
12643 m_out.constInt32(DirectArgumentsType));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000012644
12645 case Array::ScopedArguments:
12646 return m_out.equal(
benjamin@webkit.org2e864d22015-11-17 06:20:21 +000012647 m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoType),
12648 m_out.constInt32(ScopedArgumentsType));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000012649
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +000012650 default:
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +000012651 return m_out.equal(
benjamin@webkit.org2e864d22015-11-17 06:20:21 +000012652 m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoType),
12653 m_out.constInt32(typeForTypedArrayType(arrayMode.typedArrayType())));
fpizlo@apple.com9bb008a2013-09-07 21:13:55 +000012654 }
12655 }
12656
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012657 LValue isFunction(LValue cell, SpeculatedType type = SpecFullTop)
12658 {
12659 if (LValue proven = isProvenValue(type & SpecCell, SpecFunction))
12660 return proven;
12661 return isType(cell, JSFunctionType);
12662 }
12663 LValue isNotFunction(LValue cell, SpeculatedType type = SpecFullTop)
12664 {
12665 if (LValue proven = isProvenValue(type & SpecCell, ~SpecFunction))
12666 return proven;
12667 return isNotType(cell, JSFunctionType);
12668 }
fpizlo@apple.comb8823d52015-05-03 00:15:27 +000012669
12670 LValue isExoticForTypeof(LValue cell, SpeculatedType type = SpecFullTop)
12671 {
12672 if (!(type & SpecObjectOther))
12673 return m_out.booleanFalse;
benjamin@webkit.org2e864d22015-11-17 06:20:21 +000012674 return m_out.testNonZero32(
12675 m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoFlags),
12676 m_out.constInt32(MasqueradesAsUndefined | TypeOfShouldCallGetCallData));
fpizlo@apple.comb8823d52015-05-03 00:15:27 +000012677 }
mark.lam@apple.com2c87b1a2016-04-20 00:02:07 +000012678
fpizlo@apple.com44b4a232013-11-09 04:24:27 +000012679 LValue isType(LValue cell, JSType type)
12680 {
12681 return m_out.equal(
benjamin@webkit.org2e864d22015-11-17 06:20:21 +000012682 m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoType),
12683 m_out.constInt32(type));
fpizlo@apple.com44b4a232013-11-09 04:24:27 +000012684 }
12685
12686 LValue isNotType(LValue cell, JSType type)
12687 {
fpizlo@apple.com959a2c42015-12-22 21:59:59 +000012688 return m_out.logicalNot(isType(cell, type));
fpizlo@apple.com44b4a232013-11-09 04:24:27 +000012689 }
12690
oliver@apple.comea771492013-07-25 03:58:38 +000012691 void speculateObject(Edge edge, LValue cell)
12692 {
oliver@apple.com39478942013-07-25 04:03:18 +000012693 FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecObject, isNotObject(cell));
oliver@apple.comea771492013-07-25 03:58:38 +000012694 }
12695
12696 void speculateObject(Edge edge)
12697 {
12698 speculateObject(edge, lowCell(edge));
12699 }
utatane.tea@gmail.com0350d7d2016-09-16 21:17:33 +000012700
12701 void speculateArray(Edge edge, LValue cell)
12702 {
12703 FTL_TYPE_CHECK(
12704 jsValueValue(cell), edge, SpecArray, isNotType(cell, ArrayType));
12705 }
12706
12707 void speculateArray(Edge edge)
12708 {
12709 speculateArray(edge, lowCell(edge));
12710 }
oliver@apple.comea771492013-07-25 03:58:38 +000012711
fpizlo@apple.coma398a562014-08-06 21:32:55 +000012712 void speculateFunction(Edge edge, LValue cell)
12713 {
12714 FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecFunction, isNotFunction(cell));
12715 }
12716
12717 void speculateFunction(Edge edge)
12718 {
12719 speculateFunction(edge, lowCell(edge));
12720 }
12721
fpizlo@apple.comfa258dc2013-09-07 05:47:57 +000012722 void speculateObjectOrOther(Edge edge)
12723 {
12724 if (!m_interpreter.needsTypeCheck(edge))
12725 return;
12726
fpizlo@apple.coma398a562014-08-06 21:32:55 +000012727 LValue value = lowJSValue(edge, ManualOperandSpeculation);
fpizlo@apple.comfa258dc2013-09-07 05:47:57 +000012728
fpizlo@apple.com91331742016-03-07 02:07:28 +000012729 LBasicBlock cellCase = m_out.newBlock();
12730 LBasicBlock primitiveCase = m_out.newBlock();
12731 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.comfa258dc2013-09-07 05:47:57 +000012732
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000012733 m_out.branch(isNotCell(value, provenType(edge)), unsure(primitiveCase), unsure(cellCase));
fpizlo@apple.comfa258dc2013-09-07 05:47:57 +000012734
12735 LBasicBlock lastNext = m_out.appendTo(cellCase, primitiveCase);
12736
12737 FTL_TYPE_CHECK(
fpizlo@apple.com76e5b2792014-02-11 20:28:59 +000012738 jsValueValue(value), edge, (~SpecCell) | SpecObject, isNotObject(value));
fpizlo@apple.comfa258dc2013-09-07 05:47:57 +000012739
12740 m_out.jump(continuation);
12741
12742 m_out.appendTo(primitiveCase, continuation);
12743
12744 FTL_TYPE_CHECK(
fpizlo@apple.com312efcd2014-03-10 22:11:35 +000012745 jsValueValue(value), edge, SpecCell | SpecOther, isNotOther(value));
fpizlo@apple.comfa258dc2013-09-07 05:47:57 +000012746
12747 m_out.jump(continuation);
12748
12749 m_out.appendTo(continuation, lastNext);
12750 }
12751
fpizlo@apple.com44b4a232013-11-09 04:24:27 +000012752 void speculateFinalObject(Edge edge, LValue cell)
12753 {
12754 FTL_TYPE_CHECK(
12755 jsValueValue(cell), edge, SpecFinalObject, isNotType(cell, FinalObjectType));
12756 }
12757
12758 void speculateFinalObject(Edge edge)
12759 {
12760 speculateFinalObject(edge, lowCell(edge));
12761 }
12762
fpizlo@apple.come799b862016-03-01 21:18:42 +000012763 void speculateRegExpObject(Edge edge, LValue cell)
12764 {
12765 FTL_TYPE_CHECK(
12766 jsValueValue(cell), edge, SpecRegExpObject, isNotType(cell, RegExpObjectType));
12767 }
12768
12769 void speculateRegExpObject(Edge edge)
12770 {
12771 speculateRegExpObject(edge, lowCell(edge));
12772 }
sbarati@apple.com21fc86e2016-09-06 23:22:01 +000012773
utatane.tea@gmail.com4a748b12016-09-17 06:32:50 +000012774 void speculateProxyObject(Edge edge, LValue cell)
12775 {
12776 FTL_TYPE_CHECK(
12777 jsValueValue(cell), edge, SpecProxyObject, isNotType(cell, ProxyObjectType));
12778 }
12779
12780 void speculateProxyObject(Edge edge)
12781 {
12782 speculateProxyObject(edge, lowCell(edge));
12783 }
12784
12785 void speculateDerivedArray(Edge edge, LValue cell)
12786 {
12787 FTL_TYPE_CHECK(
12788 jsValueValue(cell), edge, SpecDerivedArray, isNotType(cell, DerivedArrayType));
12789 }
12790
12791 void speculateDerivedArray(Edge edge)
12792 {
12793 speculateDerivedArray(edge, lowCell(edge));
12794 }
12795
sbarati@apple.com21fc86e2016-09-06 23:22:01 +000012796 void speculateMapObject(Edge edge, LValue cell)
12797 {
12798 FTL_TYPE_CHECK(
12799 jsValueValue(cell), edge, SpecMapObject, isNotType(cell, JSMapType));
12800 }
12801
12802 void speculateMapObject(Edge edge)
12803 {
12804 speculateMapObject(edge, lowCell(edge));
12805 }
12806
12807 void speculateSetObject(Edge edge, LValue cell)
12808 {
12809 FTL_TYPE_CHECK(
12810 jsValueValue(cell), edge, SpecSetObject, isNotType(cell, JSSetType));
12811 }
12812
12813 void speculateSetObject(Edge edge)
12814 {
12815 speculateSetObject(edge, lowCell(edge));
12816 }
fpizlo@apple.come799b862016-03-01 21:18:42 +000012817
oliver@apple.com39478942013-07-25 04:03:18 +000012818 void speculateString(Edge edge, LValue cell)
12819 {
fpizlo@apple.com385a33a2014-03-18 20:53:07 +000012820 FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecString | ~SpecCell, isNotString(cell));
oliver@apple.com39478942013-07-25 04:03:18 +000012821 }
12822
12823 void speculateString(Edge edge)
12824 {
12825 speculateString(edge, lowCell(edge));
12826 }
12827
fpizlo@apple.com91331742016-03-07 02:07:28 +000012828 void speculateStringOrOther(Edge edge, LValue value)
12829 {
12830 LBasicBlock cellCase = m_out.newBlock();
12831 LBasicBlock notCellCase = m_out.newBlock();
12832 LBasicBlock continuation = m_out.newBlock();
12833
12834 m_out.branch(isCell(value, provenType(edge)), unsure(cellCase), unsure(notCellCase));
12835
12836 LBasicBlock lastNext = m_out.appendTo(cellCase, notCellCase);
12837
12838 FTL_TYPE_CHECK(jsValueValue(value), edge, (~SpecCell) | SpecString, isNotString(value));
12839
12840 m_out.jump(continuation);
12841 m_out.appendTo(notCellCase, continuation);
12842
12843 FTL_TYPE_CHECK(jsValueValue(value), edge, SpecCell | SpecOther, isNotOther(value));
12844
12845 m_out.jump(continuation);
12846 m_out.appendTo(continuation, lastNext);
12847 }
12848
12849 void speculateStringOrOther(Edge edge)
12850 {
12851 speculateStringOrOther(edge, lowJSValue(edge, ManualOperandSpeculation));
12852 }
12853
fpizlo@apple.com385a33a2014-03-18 20:53:07 +000012854 void speculateStringIdent(Edge edge, LValue string, LValue stringImpl)
12855 {
12856 if (!m_interpreter.needsTypeCheck(edge, SpecStringIdent | ~SpecString))
12857 return;
12858
12859 speculate(BadType, jsValueValue(string), edge.node(), m_out.isNull(stringImpl));
12860 speculate(
12861 BadType, jsValueValue(string), edge.node(),
12862 m_out.testIsZero32(
12863 m_out.load32(stringImpl, m_heaps.StringImpl_hashAndFlags),
barraclough@apple.com0cde90d2014-03-20 21:05:49 +000012864 m_out.constInt32(StringImpl::flagIsAtomic())));
fpizlo@apple.com385a33a2014-03-18 20:53:07 +000012865 m_interpreter.filter(edge, SpecStringIdent | ~SpecString);
12866 }
12867
12868 void speculateStringIdent(Edge edge)
12869 {
12870 lowStringIdent(edge);
12871 }
12872
msaboff@apple.com95894332014-01-29 19:18:54 +000012873 void speculateStringObject(Edge edge)
12874 {
12875 if (!m_interpreter.needsTypeCheck(edge, SpecStringObject))
12876 return;
12877
12878 speculateStringObjectForCell(edge, lowCell(edge));
12879 m_interpreter.filter(edge, SpecStringObject);
12880 }
12881
12882 void speculateStringOrStringObject(Edge edge)
12883 {
12884 if (!m_interpreter.needsTypeCheck(edge, SpecString | SpecStringObject))
12885 return;
12886
fpizlo@apple.com91331742016-03-07 02:07:28 +000012887 LBasicBlock notString = m_out.newBlock();
12888 LBasicBlock continuation = m_out.newBlock();
msaboff@apple.com95894332014-01-29 19:18:54 +000012889
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +000012890 LValue structureID = m_out.load32(lowCell(edge), m_heaps.JSCell_structureID);
msaboff@apple.com95894332014-01-29 19:18:54 +000012891 m_out.branch(
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +000012892 m_out.equal(structureID, m_out.constInt32(vm().stringStructure->id())),
fpizlo@apple.com975ae502014-02-19 22:29:43 +000012893 unsure(continuation), unsure(notString));
msaboff@apple.com95894332014-01-29 19:18:54 +000012894
12895 LBasicBlock lastNext = m_out.appendTo(notString, continuation);
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +000012896 speculateStringObjectForStructureID(edge, structureID);
msaboff@apple.com95894332014-01-29 19:18:54 +000012897 m_out.jump(continuation);
12898
12899 m_out.appendTo(continuation, lastNext);
12900
12901 m_interpreter.filter(edge, SpecString | SpecStringObject);
12902 }
12903
12904 void speculateStringObjectForCell(Edge edge, LValue cell)
12905 {
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +000012906 speculateStringObjectForStructureID(edge, m_out.load32(cell, m_heaps.JSCell_structureID));
msaboff@apple.com95894332014-01-29 19:18:54 +000012907 }
12908
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +000012909 void speculateStringObjectForStructureID(Edge edge, LValue structureID)
msaboff@apple.com95894332014-01-29 19:18:54 +000012910 {
sbarati@apple.com239d20b2017-01-26 23:50:58 +000012911 RegisteredStructure stringObjectStructure =
12912 m_graph.registerStructure(m_graph.globalObjectFor(m_node->origin.semantic)->stringObjectStructure());
12913
12914 if (abstractStructure(edge).isSubsetOf(RegisteredStructureSet(stringObjectStructure)))
msaboff@apple.com95894332014-01-29 19:18:54 +000012915 return;
12916
12917 speculate(
12918 NotStringObject, noValue(), 0,
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000012919 m_out.notEqual(structureID, weakStructureID(stringObjectStructure)));
msaboff@apple.com95894332014-01-29 19:18:54 +000012920 }
utatane.tea@gmail.comfccd1362015-08-11 22:02:09 +000012921
12922 void speculateSymbol(Edge edge, LValue cell)
12923 {
12924 FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecSymbol | ~SpecCell, isNotSymbol(cell));
12925 }
12926
12927 void speculateSymbol(Edge edge)
12928 {
12929 speculateSymbol(edge, lowCell(edge));
12930 }
12931
oliver@apple.com410b5412013-07-25 03:59:47 +000012932 void speculateNonNullObject(Edge edge, LValue cell)
12933 {
utatane.tea@gmail.com0bfb74c2015-02-24 23:01:58 +000012934 FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecObject, isNotObject(cell));
fpizlo@apple.comd84425d2013-10-30 19:58:08 +000012935 if (masqueradesAsUndefinedWatchpointIsStillValid())
oliver@apple.com410b5412013-07-25 03:59:47 +000012936 return;
12937
12938 speculate(
12939 BadType, jsValueValue(cell), edge.node(),
benjamin@webkit.org2e864d22015-11-17 06:20:21 +000012940 m_out.testNonZero32(
12941 m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoFlags),
12942 m_out.constInt32(MasqueradesAsUndefined)));
oliver@apple.com410b5412013-07-25 03:59:47 +000012943 }
12944
oliver@apple.com32295c12013-07-25 03:59:06 +000012945 void speculateNumber(Edge edge)
12946 {
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +000012947 LValue value = lowJSValue(edge, ManualOperandSpeculation);
12948 FTL_TYPE_CHECK(jsValueValue(value), edge, SpecBytecodeNumber, isNotNumber(value));
oliver@apple.com32295c12013-07-25 03:59:06 +000012949 }
12950
fpizlo@apple.com318af072015-06-05 04:59:28 +000012951 void speculateRealNumber(Edge edge)
12952 {
12953 // Do an early return here because lowDouble() can create a lot of control flow.
12954 if (!m_interpreter.needsTypeCheck(edge))
12955 return;
12956
12957 LValue value = lowJSValue(edge, ManualOperandSpeculation);
12958 LValue doubleValue = unboxDouble(value);
12959
fpizlo@apple.com91331742016-03-07 02:07:28 +000012960 LBasicBlock intCase = m_out.newBlock();
12961 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com318af072015-06-05 04:59:28 +000012962
12963 m_out.branch(
12964 m_out.doubleEqual(doubleValue, doubleValue),
12965 usually(continuation), rarely(intCase));
12966
12967 LBasicBlock lastNext = m_out.appendTo(intCase, continuation);
12968
12969 typeCheck(
12970 jsValueValue(value), m_node->child1(), SpecBytecodeRealNumber,
12971 isNotInt32(value, provenType(m_node->child1()) & ~SpecFullDouble));
12972 m_out.jump(continuation);
12973
12974 m_out.appendTo(continuation, lastNext);
12975 }
12976
12977 void speculateDoubleRepReal(Edge edge)
oliver@apple.com32295c12013-07-25 03:59:06 +000012978 {
12979 // Do an early return here because lowDouble() can create a lot of control flow.
oliver@apple.com55d32d92013-07-25 04:05:03 +000012980 if (!m_interpreter.needsTypeCheck(edge))
oliver@apple.com32295c12013-07-25 03:59:06 +000012981 return;
12982
12983 LValue value = lowDouble(edge);
12984 FTL_TYPE_CHECK(
fpizlo@apple.com7b33e0c2014-04-15 20:26:16 +000012985 doubleValue(value), edge, SpecDoubleReal,
oliver@apple.com32295c12013-07-25 03:59:06 +000012986 m_out.doubleNotEqualOrUnordered(value, value));
12987 }
oliver@apple.com827d2cf2013-07-25 04:04:45 +000012988
mark.lam@apple.com39e9c982016-04-25 17:48:46 +000012989 void speculateDoubleRepAnyInt(Edge edge)
fpizlo@apple.comf2999932014-07-15 00:41:39 +000012990 {
12991 if (!m_interpreter.needsTypeCheck(edge))
12992 return;
12993
12994 doubleToStrictInt52(edge, lowDouble(edge));
12995 }
12996
oliver@apple.com827d2cf2013-07-25 04:04:45 +000012997 void speculateBoolean(Edge edge)
12998 {
12999 lowBoolean(edge);
13000 }
fpizlo@apple.com6921b292013-09-18 17:14:02 +000013001
fpizlo@apple.com385a33a2014-03-18 20:53:07 +000013002 void speculateNotStringVar(Edge edge)
13003 {
13004 if (!m_interpreter.needsTypeCheck(edge, ~SpecStringVar))
13005 return;
13006
13007 LValue value = lowJSValue(edge, ManualOperandSpeculation);
13008
fpizlo@apple.com91331742016-03-07 02:07:28 +000013009 LBasicBlock isCellCase = m_out.newBlock();
13010 LBasicBlock isStringCase = m_out.newBlock();
13011 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com385a33a2014-03-18 20:53:07 +000013012
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000013013 m_out.branch(isCell(value, provenType(edge)), unsure(isCellCase), unsure(continuation));
fpizlo@apple.com385a33a2014-03-18 20:53:07 +000013014
13015 LBasicBlock lastNext = m_out.appendTo(isCellCase, isStringCase);
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000013016 m_out.branch(isString(value, provenType(edge)), unsure(isStringCase), unsure(continuation));
fpizlo@apple.com385a33a2014-03-18 20:53:07 +000013017
13018 m_out.appendTo(isStringCase, continuation);
13019 speculateStringIdent(edge, value, m_out.loadPtr(value, m_heaps.JSString_value));
13020 m_out.jump(continuation);
13021
13022 m_out.appendTo(continuation, lastNext);
13023 }
13024
msaboff@apple.com95894332014-01-29 19:18:54 +000013025 void speculateNotCell(Edge edge)
13026 {
13027 if (!m_interpreter.needsTypeCheck(edge))
13028 return;
13029
fpizlo@apple.com312efcd2014-03-10 22:11:35 +000013030 LValue value = lowJSValue(edge, ManualOperandSpeculation);
msaboff@apple.com95894332014-01-29 19:18:54 +000013031 typeCheck(jsValueValue(value), edge, ~SpecCell, isCell(value));
13032 }
13033
fpizlo@apple.com312efcd2014-03-10 22:11:35 +000013034 void speculateOther(Edge edge)
13035 {
13036 if (!m_interpreter.needsTypeCheck(edge))
13037 return;
13038
13039 LValue value = lowJSValue(edge, ManualOperandSpeculation);
13040 typeCheck(jsValueValue(value), edge, SpecOther, isNotOther(value));
13041 }
13042
fpizlo@apple.come079bb52014-03-05 07:41:03 +000013043 void speculateMisc(Edge edge)
13044 {
13045 if (!m_interpreter.needsTypeCheck(edge))
13046 return;
13047
fpizlo@apple.com312efcd2014-03-10 22:11:35 +000013048 LValue value = lowJSValue(edge, ManualOperandSpeculation);
fpizlo@apple.come079bb52014-03-05 07:41:03 +000013049 typeCheck(jsValueValue(value), edge, SpecMisc, isNotMisc(value));
13050 }
keith_miller@apple.com723825f2016-07-08 16:27:35 +000013051
13052 void speculateTypedArrayIsNotNeutered(LValue base)
13053 {
13054 LBasicBlock isWasteful = m_out.newBlock();
13055 LBasicBlock continuation = m_out.newBlock();
13056
13057 LValue mode = m_out.load32(base, m_heaps.JSArrayBufferView_mode);
13058 m_out.branch(m_out.equal(mode, m_out.constInt32(WastefulTypedArray)),
13059 unsure(isWasteful), unsure(continuation));
13060
13061 LBasicBlock lastNext = m_out.appendTo(isWasteful, continuation);
13062 LValue vector = m_out.loadPtr(base, m_heaps.JSArrayBufferView_vector);
keith_miller@apple.comf084cbf2016-07-08 18:48:25 +000013063 speculate(Uncountable, jsValueValue(vector), m_node, m_out.isZero64(vector));
keith_miller@apple.com723825f2016-07-08 16:27:35 +000013064 m_out.jump(continuation);
13065
13066 m_out.appendTo(continuation, lastNext);
13067 }
13068
oliver@apple.com410b5412013-07-25 03:59:47 +000013069 bool masqueradesAsUndefinedWatchpointIsStillValid()
13070 {
fpizlo@apple.com6793a322014-02-12 05:42:32 +000013071 return m_graph.masqueradesAsUndefinedWatchpointIsStillValid(m_node->origin.semantic);
oliver@apple.com410b5412013-07-25 03:59:47 +000013072 }
13073
fpizlo@apple.com3cb36ea2015-10-05 19:35:32 +000013074 LValue loadCellState(LValue base)
mhahnenberg@apple.com72454da2014-01-03 00:24:14 +000013075 {
benjamin@webkit.org2e864d22015-11-17 06:20:21 +000013076 return m_out.load8ZeroExt32(base, m_heaps.JSCell_cellState);
mhahnenberg@apple.com72454da2014-01-03 00:24:14 +000013077 }
13078
fpizlo@apple.com9a175952016-09-28 21:55:53 +000013079 void emitStoreBarrier(LValue base, bool isFenced)
mhahnenberg@apple.com72454da2014-01-03 00:24:14 +000013080 {
fpizlo@apple.com72e75cd2017-01-10 23:41:55 +000013081 LBasicBlock recheckPath = nullptr;
13082 if (isFenced)
13083 recheckPath = m_out.newBlock();
fpizlo@apple.com91331742016-03-07 02:07:28 +000013084 LBasicBlock slowPath = m_out.newBlock();
13085 LBasicBlock continuation = m_out.newBlock();
fpizlo@apple.com72e75cd2017-01-10 23:41:55 +000013086
13087 LBasicBlock lastNext = m_out.insertNewBlocksBefore(isFenced ? recheckPath : slowPath);
mhahnenberg@apple.com72454da2014-01-03 00:24:14 +000013088
fpizlo@apple.com9a175952016-09-28 21:55:53 +000013089 LValue threshold;
13090 if (isFenced)
13091 threshold = m_out.load32(m_out.absolute(vm().heap.addressOfBarrierThreshold()));
13092 else
13093 threshold = m_out.constInt32(blackThreshold);
13094
fpizlo@apple.com975ae502014-02-19 22:29:43 +000013095 m_out.branch(
fpizlo@apple.com9a175952016-09-28 21:55:53 +000013096 m_out.above(loadCellState(base), threshold),
fpizlo@apple.com72e75cd2017-01-10 23:41:55 +000013097 usually(continuation), rarely(isFenced ? recheckPath : slowPath));
fpizlo@apple.com9a175952016-09-28 21:55:53 +000013098
fpizlo@apple.com72e75cd2017-01-10 23:41:55 +000013099 if (isFenced) {
13100 m_out.appendTo(recheckPath, slowPath);
13101
13102 m_out.fence(&m_heaps.root, &m_heaps.JSCell_cellState);
13103
13104 m_out.branch(
13105 m_out.above(loadCellState(base), m_out.constInt32(blackThreshold)),
13106 usually(continuation), rarely(slowPath));
13107 }
mhahnenberg@apple.com72454da2014-01-03 00:24:14 +000013108
fpizlo@apple.com72e75cd2017-01-10 23:41:55 +000013109 m_out.appendTo(slowPath, continuation);
fpizlo@apple.com9a175952016-09-28 21:55:53 +000013110
fpizlo@apple.com72e75cd2017-01-10 23:41:55 +000013111 LValue call = vmCall(Void, m_out.operation(operationWriteBarrierSlowPath), m_callFrame, base);
13112 m_heaps.decorateCCallRead(&m_heaps.root, call);
13113 m_heaps.decorateCCallWrite(&m_heaps.JSCell_cellState, call);
fpizlo@apple.com9a175952016-09-28 21:55:53 +000013114
mhahnenberg@apple.com72454da2014-01-03 00:24:14 +000013115 m_out.jump(continuation);
13116
13117 m_out.appendTo(continuation, lastNext);
mhahnenberg@apple.com72454da2014-01-03 00:24:14 +000013118 }
fpizlo@apple.com101a1682016-11-15 01:49:22 +000013119
13120 void mutatorFence()
13121 {
fpizlo@apple.com0ef43952016-12-08 22:14:50 +000013122 if (isX86()) {
fpizlo@apple.com101a1682016-11-15 01:49:22 +000013123 m_out.fence(&m_heaps.root, nullptr);
13124 return;
13125 }
13126
13127 LBasicBlock slowPath = m_out.newBlock();
13128 LBasicBlock continuation = m_out.newBlock();
13129
13130 LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
13131
13132 m_out.branch(
13133 m_out.load8ZeroExt32(m_out.absolute(vm().heap.addressOfMutatorShouldBeFenced())),
13134 rarely(slowPath), usually(continuation));
13135
fpizlo@apple.combd9e8ed2016-11-16 22:24:45 +000013136 m_out.appendTo(slowPath, continuation);
fpizlo@apple.com101a1682016-11-15 01:49:22 +000013137
13138 m_out.fence(&m_heaps.root, nullptr);
13139 m_out.jump(continuation);
13140
13141 m_out.appendTo(continuation, lastNext);
13142 }
13143
fpizlo@apple.com0ef43952016-12-08 22:14:50 +000013144 void nukeStructureAndSetButterfly(LValue butterfly, LValue object)
fpizlo@apple.com101a1682016-11-15 01:49:22 +000013145 {
fpizlo@apple.com0ef43952016-12-08 22:14:50 +000013146 if (isX86()) {
13147 m_out.store32(
13148 m_out.bitOr(
13149 m_out.load32(object, m_heaps.JSCell_structureID),
13150 m_out.constInt32(nukedStructureIDBit())),
13151 object, m_heaps.JSCell_structureID);
fpizlo@apple.com101a1682016-11-15 01:49:22 +000013152 m_out.fence(&m_heaps.root, nullptr);
13153 m_out.storePtr(butterfly, object, m_heaps.JSObject_butterfly);
13154 m_out.fence(&m_heaps.root, nullptr);
13155 return;
13156 }
13157
13158 LBasicBlock fastPath = m_out.newBlock();
13159 LBasicBlock slowPath = m_out.newBlock();
13160 LBasicBlock continuation = m_out.newBlock();
13161
13162 LBasicBlock lastNext = m_out.insertNewBlocksBefore(fastPath);
13163
13164 m_out.branch(
13165 m_out.load8ZeroExt32(m_out.absolute(vm().heap.addressOfMutatorShouldBeFenced())),
13166 rarely(slowPath), usually(fastPath));
13167
fpizlo@apple.combd9e8ed2016-11-16 22:24:45 +000013168 m_out.appendTo(fastPath, slowPath);
fpizlo@apple.com101a1682016-11-15 01:49:22 +000013169
13170 m_out.storePtr(butterfly, object, m_heaps.JSObject_butterfly);
13171 m_out.jump(continuation);
13172
fpizlo@apple.combd9e8ed2016-11-16 22:24:45 +000013173 m_out.appendTo(slowPath, continuation);
fpizlo@apple.com101a1682016-11-15 01:49:22 +000013174
fpizlo@apple.com0ef43952016-12-08 22:14:50 +000013175 m_out.store32(
13176 m_out.bitOr(
13177 m_out.load32(object, m_heaps.JSCell_structureID),
13178 m_out.constInt32(nukedStructureIDBit())),
13179 object, m_heaps.JSCell_structureID);
fpizlo@apple.com101a1682016-11-15 01:49:22 +000013180 m_out.fence(&m_heaps.root, nullptr);
13181 m_out.storePtr(butterfly, object, m_heaps.JSObject_butterfly);
13182 m_out.fence(&m_heaps.root, nullptr);
13183 m_out.jump(continuation);
13184
13185 m_out.appendTo(continuation, lastNext);
13186 }
mhahnenberg@apple.com72454da2014-01-03 00:24:14 +000013187
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +000013188 template<typename... Args>
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +000013189 LValue vmCall(LType type, LValue function, Args... args)
oliver@apple.com39478942013-07-25 04:03:18 +000013190 {
13191 callPreflight();
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +000013192 LValue result = m_out.call(type, function, args...);
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +000013193 callCheck();
oliver@apple.com8c55ed02013-07-25 04:04:01 +000013194 return result;
13195 }
oliver@apple.com39478942013-07-25 04:03:18 +000013196
13197 void callPreflight(CodeOrigin codeOrigin)
13198 {
sbarati@apple.com5bebda72015-11-10 07:48:54 +000013199 CallSiteIndex callSiteIndex = m_ftlState.jitCode->common.addCodeOrigin(codeOrigin);
oliver@apple.com39478942013-07-25 04:03:18 +000013200 m_out.store32(
sbarati@apple.com5bebda72015-11-10 07:48:54 +000013201 m_out.constInt32(callSiteIndex.bits()),
mark.lam@apple.com2bd89342016-07-08 22:58:15 +000013202 tagFor(CallFrameSlot::argumentCount));
oliver@apple.com39478942013-07-25 04:03:18 +000013203 }
sbarati@apple.com76af72c2015-10-21 18:44:44 +000013204
oliver@apple.com39478942013-07-25 04:03:18 +000013205 void callPreflight()
13206 {
sbarati@apple.com76af72c2015-10-21 18:44:44 +000013207 callPreflight(codeOriginDescriptionOfCallSite());
13208 }
msaboff@apple.comcdd479b2015-09-30 22:28:08 +000013209
sbarati@apple.com76af72c2015-10-21 18:44:44 +000013210 CodeOrigin codeOriginDescriptionOfCallSite() const
13211 {
13212 CodeOrigin codeOrigin = m_node->origin.semantic;
msaboff@apple.comcdd479b2015-09-30 22:28:08 +000013213 if (m_node->op() == TailCallInlinedCaller
13214 || m_node->op() == TailCallVarargsInlinedCaller
fpizlo@apple.comf0b30cb2016-10-18 18:30:05 +000013215 || m_node->op() == TailCallForwardVarargsInlinedCaller
13216 || m_node->op() == DirectTailCallInlinedCaller) {
sbarati@apple.com76af72c2015-10-21 18:44:44 +000013217 // This case arises when you have a situation like this:
13218 // foo makes a call to bar, bar is inlined in foo. bar makes a call
13219 // to baz and baz is inlined in bar. And then baz makes a tail-call to jaz,
13220 // and jaz is inlined in baz. We want the callframe for jaz to appear to
13221 // have caller be bar.
msaboff@apple.comcde665e2015-11-03 20:02:02 +000013222 codeOrigin = *codeOrigin.inlineCallFrame->getCallerSkippingTailCalls();
sbarati@apple.com76af72c2015-10-21 18:44:44 +000013223 }
msaboff@apple.comcdd479b2015-09-30 22:28:08 +000013224
sbarati@apple.com76af72c2015-10-21 18:44:44 +000013225 return codeOrigin;
oliver@apple.com39478942013-07-25 04:03:18 +000013226 }
13227
fpizlo@apple.com8fefdd32015-02-18 19:55:47 +000013228 void callCheck()
oliver@apple.com39478942013-07-25 04:03:18 +000013229 {
mark.lam@apple.comee3c4102015-10-14 18:57:07 +000013230 if (Options::useExceptionFuzz())
fpizlo@apple.com994d4532016-07-03 19:34:55 +000013231 m_out.call(Void, m_out.operation(operationExceptionFuzz), m_callFrame);
fpizlo@apple.com9f1dad42014-07-18 04:34:16 +000013232
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +000013233 LValue exception = m_out.load64(m_out.absolute(vm().addressOfException()));
sbarati@apple.com5bebda72015-11-10 07:48:54 +000013234 LValue hadException = m_out.notZero64(exception);
13235
fpizlo@apple.com8d59d302016-01-06 20:49:32 +000013236 CodeOrigin opCatchOrigin;
13237 HandlerInfo* exceptionHandler;
13238 if (m_graph.willCatchExceptionInMachineFrame(m_origin.forExit, opCatchOrigin, exceptionHandler)) {
13239 bool exitOK = true;
13240 bool isExceptionHandler = true;
13241 appendOSRExit(
sbarati@apple.comfb6a8e22016-01-29 19:46:01 +000013242 ExceptionCheck, noValue(), nullptr, hadException,
fpizlo@apple.com8d59d302016-01-06 20:49:32 +000013243 m_origin.withForExitAndExitOK(opCatchOrigin, exitOK), isExceptionHandler);
sbarati@apple.com5bebda72015-11-10 07:48:54 +000013244 return;
fpizlo@apple.com8d59d302016-01-06 20:49:32 +000013245 }
sbarati@apple.com5bebda72015-11-10 07:48:54 +000013246
fpizlo@apple.com91331742016-03-07 02:07:28 +000013247 LBasicBlock continuation = m_out.newBlock();
sbarati@apple.com5bebda72015-11-10 07:48:54 +000013248
oliver@apple.com39478942013-07-25 04:03:18 +000013249 m_out.branch(
sbarati@apple.com5bebda72015-11-10 07:48:54 +000013250 hadException, rarely(m_handleExceptions), usually(continuation));
13251
msaboff@apple.com95894332014-01-29 19:18:54 +000013252 m_out.appendTo(continuation);
oliver@apple.com39478942013-07-25 04:03:18 +000013253 }
sbarati@apple.com5bebda72015-11-10 07:48:54 +000013254
fpizlo@apple.com45e45652016-01-07 21:20:37 +000013255 RefPtr<PatchpointExceptionHandle> preparePatchpointForExceptions(PatchpointValue* value)
13256 {
13257 CodeOrigin opCatchOrigin;
13258 HandlerInfo* exceptionHandler;
13259 bool willCatchException = m_graph.willCatchExceptionInMachineFrame(m_origin.forExit, opCatchOrigin, exceptionHandler);
13260 if (!willCatchException)
13261 return PatchpointExceptionHandle::defaultHandle(m_ftlState);
13262
13263 if (verboseCompilationEnabled()) {
13264 dataLog(" Patchpoint exception OSR exit #", m_ftlState.jitCode->osrExitDescriptors.size(), " with availability: ", availabilityMap(), "\n");
13265 if (!m_availableRecoveries.isEmpty())
13266 dataLog(" Available recoveries: ", listDump(m_availableRecoveries), "\n");
13267 }
13268
13269 bool exitOK = true;
13270 NodeOrigin origin = m_origin.withForExitAndExitOK(opCatchOrigin, exitOK);
13271
13272 OSRExitDescriptor* exitDescriptor = appendOSRExitDescriptor(noValue(), nullptr);
13273
13274 // Compute the offset into the StackmapGenerationParams where we will find the exit arguments
13275 // we are about to append. We need to account for both the children we've already added, and
13276 // for the possibility of a result value if the patchpoint is not void.
13277 unsigned offset = value->numChildren();
13278 if (value->type() != Void)
13279 offset++;
13280
13281 // Use LateColdAny to ensure that the stackmap arguments interfere with the patchpoint's
13282 // result and with any late-clobbered registers.
13283 value->appendVectorWithRep(
13284 buildExitArguments(exitDescriptor, opCatchOrigin, noValue()),
13285 ValueRep::LateColdAny);
13286
13287 return PatchpointExceptionHandle::create(
13288 m_ftlState, exitDescriptor, origin, offset, *exceptionHandler);
13289 }
sbarati@apple.com5bebda72015-11-10 07:48:54 +000013290
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +000013291 LBasicBlock lowBlock(DFG::BasicBlock* block)
oliver@apple.com39478942013-07-25 04:03:18 +000013292 {
oliver@apple.com426f5b02013-07-25 04:04:27 +000013293 return m_blocks.get(block);
oliver@apple.com39478942013-07-25 04:03:18 +000013294 }
sbarati@apple.com5bebda72015-11-10 07:48:54 +000013295
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +000013296 OSRExitDescriptor* appendOSRExitDescriptor(FormattedValue lowValue, Node* highValue)
13297 {
13298 return &m_ftlState.jitCode->osrExitDescriptors.alloc(
mark.lam@apple.com6d9ff662016-11-10 21:19:52 +000013299 lowValue.format(), m_graph.methodOfGettingAValueProfileFor(m_node, highValue),
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +000013300 availabilityMap().m_locals.numberOfArguments(),
13301 availabilityMap().m_locals.numberOfLocals());
13302 }
oliver@apple.com39478942013-07-25 04:03:18 +000013303
oliver@apple.comea771492013-07-25 03:58:38 +000013304 void appendOSRExit(
sbarati@apple.com5bebda72015-11-10 07:48:54 +000013305 ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition,
13306 NodeOrigin origin, bool isExceptionHandler = false)
oliver@apple.comea771492013-07-25 03:58:38 +000013307 {
msaboff@apple.com95894332014-01-29 19:18:54 +000013308 if (verboseCompilationEnabled()) {
sbarati@apple.comcda241d2015-10-19 20:29:45 +000013309 dataLog(" OSR exit #", m_ftlState.jitCode->osrExitDescriptors.size(), " with availability: ", availabilityMap(), "\n");
msaboff@apple.com95894332014-01-29 19:18:54 +000013310 if (!m_availableRecoveries.isEmpty())
13311 dataLog(" Available recoveries: ", listDump(m_availableRecoveries), "\n");
13312 }
fpizlo@apple.comf29186e2015-08-26 19:24:41 +000013313
sbarati@apple.com5bebda72015-11-10 07:48:54 +000013314 DFG_ASSERT(m_graph, m_node, origin.exitOK);
commit-queue@webkit.org91b902c2016-08-20 02:00:44 +000013315
13316 if (!isExceptionHandler
13317 && Options::useOSRExitFuzz()
13318 && canUseOSRExitFuzzing(m_graph.baselineCodeBlockFor(m_node->origin.semantic))
13319 && doOSRExitFuzzing()) {
fpizlo@apple.comf19f0142015-07-03 01:48:01 +000013320 LValue numberOfFuzzChecks = m_out.add(
13321 m_out.load32(m_out.absolute(&g_numberOfOSRExitFuzzChecks)),
13322 m_out.int32One);
13323
13324 m_out.store32(numberOfFuzzChecks, m_out.absolute(&g_numberOfOSRExitFuzzChecks));
13325
13326 if (unsigned atOrAfter = Options::fireOSRExitFuzzAtOrAfter()) {
13327 failCondition = m_out.bitOr(
13328 failCondition,
13329 m_out.aboveOrEqual(numberOfFuzzChecks, m_out.constInt32(atOrAfter)));
13330 }
13331 if (unsigned at = Options::fireOSRExitFuzzAt()) {
13332 failCondition = m_out.bitOr(
13333 failCondition,
13334 m_out.equal(numberOfFuzzChecks, m_out.constInt32(at)));
13335 }
13336 }
fpizlo@apple.com002405c2013-11-18 01:46:48 +000013337
fpizlo@apple.com12835772015-09-21 20:49:04 +000013338 if (failCondition == m_out.booleanFalse)
13339 return;
13340
fpizlo@apple.combce60f82015-11-19 20:03:22 +000013341 blessSpeculation(
sbarati@apple.comfb6a8e22016-01-29 19:46:01 +000013342 m_out.speculate(failCondition), kind, lowValue, highValue, origin);
oliver@apple.com62242ce2013-07-25 04:04:29 +000013343 }
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +000013344
sbarati@apple.comfb6a8e22016-01-29 19:46:01 +000013345 void blessSpeculation(CheckValue* value, ExitKind kind, FormattedValue lowValue, Node* highValue, NodeOrigin origin)
fpizlo@apple.combce60f82015-11-19 20:03:22 +000013346 {
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +000013347 OSRExitDescriptor* exitDescriptor = appendOSRExitDescriptor(lowValue, highValue);
fpizlo@apple.come362fbc2015-12-03 20:01:57 +000013348
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +000013349 value->appendColdAnys(buildExitArguments(exitDescriptor, origin.forExit, lowValue));
fpizlo@apple.come362fbc2015-12-03 20:01:57 +000013350
13351 State* state = &m_ftlState;
fpizlo@apple.combce60f82015-11-19 20:03:22 +000013352 value->setGenerator(
fpizlo@apple.come362fbc2015-12-03 20:01:57 +000013353 [=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +000013354 exitDescriptor->emitOSRExit(
sbarati@apple.comfb6a8e22016-01-29 19:46:01 +000013355 *state, kind, origin, jit, params, 0);
fpizlo@apple.combce60f82015-11-19 20:03:22 +000013356 });
13357 }
fpizlo@apple.combce60f82015-11-19 20:03:22 +000013358
13359 StackmapArgumentList buildExitArguments(
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +000013360 OSRExitDescriptor* exitDescriptor, CodeOrigin exitOrigin, FormattedValue lowValue,
fpizlo@apple.combce60f82015-11-19 20:03:22 +000013361 unsigned offsetOfExitArgumentsInStackmapLocations = 0)
13362 {
13363 StackmapArgumentList result;
13364 buildExitArguments(
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +000013365 exitDescriptor, exitOrigin, result, lowValue, offsetOfExitArgumentsInStackmapLocations);
fpizlo@apple.combce60f82015-11-19 20:03:22 +000013366 return result;
13367 }
fpizlo@apple.comed46a0b2013-10-31 22:49:51 +000013368
13369 void buildExitArguments(
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +000013370 OSRExitDescriptor* exitDescriptor, CodeOrigin exitOrigin, StackmapArgumentList& arguments, FormattedValue lowValue,
fpizlo@apple.com13969912015-12-01 22:12:42 +000013371 unsigned offsetOfExitArgumentsInStackmapLocations = 0)
fpizlo@apple.comed46a0b2013-10-31 22:49:51 +000013372 {
oliver@apple.comea771492013-07-25 03:58:38 +000013373 if (!!lowValue)
13374 arguments.append(lowValue.value());
13375
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000013376 AvailabilityMap availabilityMap = this->availabilityMap();
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +000013377 availabilityMap.pruneByLiveness(m_graph, exitOrigin);
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000013378
13379 HashMap<Node*, ExitTimeObjectMaterialization*> map;
13380 availabilityMap.forEachAvailability(
13381 [&] (Availability availability) {
13382 if (!availability.shouldUseNode())
13383 return;
13384
13385 Node* node = availability.node();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000013386 if (!node->isPhantomAllocation())
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000013387 return;
13388
13389 auto result = map.add(node, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000013390 if (result.isNewEntry) {
13391 result.iterator->value =
fpizlo@apple.come362fbc2015-12-03 20:01:57 +000013392 exitDescriptor->m_materializations.add(node->op(), node->origin.semantic);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000013393 }
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000013394 });
13395
fpizlo@apple.come362fbc2015-12-03 20:01:57 +000013396 for (unsigned i = 0; i < exitDescriptor->m_values.size(); ++i) {
13397 int operand = exitDescriptor->m_values.operandForIndex(i);
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000013398
13399 Availability availability = availabilityMap.m_locals[i];
13400
fpizlo@apple.comd1c9afd2016-06-16 22:18:06 +000013401 if (Options::validateFTLOSRExitLiveness()
13402 && m_graph.m_plan.mode != FTLForOSREntryMode) {
13403
13404 if (availability.isDead() && m_graph.isLiveInBytecode(VirtualRegister(operand), exitOrigin))
13405 DFG_CRASH(m_graph, m_node, toCString("Live bytecode local not available: operand = ", VirtualRegister(operand), ", availability = ", availability, ", origin = ", exitOrigin).data());
fpizlo@apple.com002405c2013-11-18 01:46:48 +000013406 }
sbarati@apple.com621078b2015-11-13 21:36:18 +000013407 ExitValue exitValue = exitValueForAvailability(arguments, map, availability);
13408 if (exitValue.hasIndexInStackmapLocations())
13409 exitValue.adjustStackmapLocationsIndexByOffset(offsetOfExitArgumentsInStackmapLocations);
fpizlo@apple.come362fbc2015-12-03 20:01:57 +000013410 exitDescriptor->m_values[i] = exitValue;
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000013411 }
13412
13413 for (auto heapPair : availabilityMap.m_heap) {
13414 Node* node = heapPair.key.base();
13415 ExitTimeObjectMaterialization* materialization = map.get(node);
sbarati@apple.com621078b2015-11-13 21:36:18 +000013416 ExitValue exitValue = exitValueForAvailability(arguments, map, heapPair.value);
13417 if (exitValue.hasIndexInStackmapLocations())
13418 exitValue.adjustStackmapLocationsIndexByOffset(offsetOfExitArgumentsInStackmapLocations);
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000013419 materialization->add(
13420 heapPair.key.descriptor(),
sbarati@apple.com621078b2015-11-13 21:36:18 +000013421 exitValue);
oliver@apple.comea771492013-07-25 03:58:38 +000013422 }
13423
basile_clement@apple.com849b11e2015-05-07 20:59:44 +000013424 if (verboseCompilationEnabled()) {
fpizlo@apple.come362fbc2015-12-03 20:01:57 +000013425 dataLog(" Exit values: ", exitDescriptor->m_values, "\n");
13426 if (!exitDescriptor->m_materializations.isEmpty()) {
basile_clement@apple.comc1c6cde2015-05-07 18:39:46 +000013427 dataLog(" Materializations: \n");
fpizlo@apple.come362fbc2015-12-03 20:01:57 +000013428 for (ExitTimeObjectMaterialization* materialization : exitDescriptor->m_materializations)
fpizlo@apple.com09b14f92015-05-13 05:21:16 +000013429 dataLog(" ", pointerDump(materialization), "\n");
basile_clement@apple.comc1c6cde2015-05-07 18:39:46 +000013430 }
basile_clement@apple.com849b11e2015-05-07 20:59:44 +000013431 }
fpizlo@apple.comed46a0b2013-10-31 22:49:51 +000013432 }
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +000013433
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000013434 ExitValue exitValueForAvailability(
sbarati@apple.comc13003f2015-11-10 20:42:32 +000013435 StackmapArgumentList& arguments, const HashMap<Node*, ExitTimeObjectMaterialization*>& map,
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000013436 Availability availability)
13437 {
13438 FlushedAt flush = availability.flushedAt();
13439 switch (flush.format()) {
13440 case DeadFlush:
13441 case ConflictingFlush:
13442 if (availability.hasNode())
13443 return exitValueForNode(arguments, map, availability.node());
13444
13445 // This means that the value is dead. It could be dead in bytecode or it could have
13446 // been killed by our DCE, which can sometimes kill things even if they were live in
13447 // bytecode.
13448 return ExitValue::dead();
13449
13450 case FlushedJSValue:
13451 case FlushedCell:
13452 case FlushedBoolean:
13453 return ExitValue::inJSStack(flush.virtualRegister());
13454
13455 case FlushedInt32:
13456 return ExitValue::inJSStackAsInt32(flush.virtualRegister());
13457
13458 case FlushedInt52:
13459 return ExitValue::inJSStackAsInt52(flush.virtualRegister());
13460
13461 case FlushedDouble:
13462 return ExitValue::inJSStackAsDouble(flush.virtualRegister());
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000013463 }
13464
msaboff@apple.com044ba8d2015-02-18 23:52:16 +000013465 DFG_CRASH(m_graph, m_node, "Invalid flush format");
dbatyai.u-szeged@partner.samsung.comb107a6e2014-10-21 10:18:13 +000013466 return ExitValue::dead();
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000013467 }
13468
13469 ExitValue exitValueForNode(
sbarati@apple.comc13003f2015-11-10 20:42:32 +000013470 StackmapArgumentList& arguments, const HashMap<Node*, ExitTimeObjectMaterialization*>& map,
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000013471 Node* node)
oliver@apple.comea771492013-07-25 03:58:38 +000013472 {
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +000013473 // NOTE: In FTL->B3, we cannot generate code here, because m_output is positioned after the
13474 // stackmap value. Like all values, the stackmap value cannot use a child that is defined after
13475 // it.
13476
oliver@apple.comea771492013-07-25 03:58:38 +000013477 ASSERT(node->shouldGenerate());
13478 ASSERT(node->hasResult());
13479
fpizlo@apple.com7e2b5292014-09-20 21:52:14 +000013480 if (node) {
13481 switch (node->op()) {
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000013482 case BottomValue:
13483 // This might arise in object materializations. I actually doubt that it would,
13484 // but it seems worthwhile to be conservative.
13485 return ExitValue::dead();
13486
fpizlo@apple.com7e2b5292014-09-20 21:52:14 +000013487 case JSConstant:
13488 case Int52Constant:
13489 case DoubleConstant:
13490 return ExitValue::constant(node->asJSValue());
13491
fpizlo@apple.com7e2b5292014-09-20 21:52:14 +000013492 default:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000013493 if (node->isPhantomAllocation())
13494 return ExitValue::materializeNewObject(map.get(node));
fpizlo@apple.com7e2b5292014-09-20 21:52:14 +000013495 break;
13496 }
13497 }
oliver@apple.comea771492013-07-25 03:58:38 +000013498
msaboff@apple.com95894332014-01-29 19:18:54 +000013499 for (unsigned i = 0; i < m_availableRecoveries.size(); ++i) {
13500 AvailableRecovery recovery = m_availableRecoveries[i];
13501 if (recovery.node() != node)
13502 continue;
fpizlo@apple.com7e2b5292014-09-20 21:52:14 +000013503 ExitValue result = ExitValue::recovery(
msaboff@apple.com95894332014-01-29 19:18:54 +000013504 recovery.opcode(), arguments.size(), arguments.size() + 1,
13505 recovery.format());
13506 arguments.append(recovery.left());
13507 arguments.append(recovery.right());
fpizlo@apple.com7e2b5292014-09-20 21:52:14 +000013508 return result;
msaboff@apple.com95894332014-01-29 19:18:54 +000013509 }
13510
oliver@apple.com827d2cf2013-07-25 04:04:45 +000013511 LoweredNodeValue value = m_int32Values.get(node);
fpizlo@apple.com7e2b5292014-09-20 21:52:14 +000013512 if (isValid(value))
basile_clement@apple.com3ed5a3a2015-09-04 18:24:38 +000013513 return exitArgument(arguments, DataFormatInt32, value.value());
oliver@apple.comea771492013-07-25 03:58:38 +000013514
fpizlo@apple.com6921b292013-09-18 17:14:02 +000013515 value = m_int52Values.get(node);
fpizlo@apple.com7e2b5292014-09-20 21:52:14 +000013516 if (isValid(value))
basile_clement@apple.com3ed5a3a2015-09-04 18:24:38 +000013517 return exitArgument(arguments, DataFormatInt52, value.value());
fpizlo@apple.com6921b292013-09-18 17:14:02 +000013518
13519 value = m_strictInt52Values.get(node);
fpizlo@apple.com7e2b5292014-09-20 21:52:14 +000013520 if (isValid(value))
basile_clement@apple.com3ed5a3a2015-09-04 18:24:38 +000013521 return exitArgument(arguments, DataFormatStrictInt52, value.value());
fpizlo@apple.com6921b292013-09-18 17:14:02 +000013522
oliver@apple.com827d2cf2013-07-25 04:04:45 +000013523 value = m_booleanValues.get(node);
fpizlo@apple.com9ed1b632015-12-07 19:17:56 +000013524 if (isValid(value))
13525 return exitArgument(arguments, DataFormatBoolean, value.value());
oliver@apple.comea771492013-07-25 03:58:38 +000013526
oliver@apple.com827d2cf2013-07-25 04:04:45 +000013527 value = m_jsValueValues.get(node);
fpizlo@apple.com7e2b5292014-09-20 21:52:14 +000013528 if (isValid(value))
basile_clement@apple.com3ed5a3a2015-09-04 18:24:38 +000013529 return exitArgument(arguments, DataFormatJS, value.value());
oliver@apple.comea771492013-07-25 03:58:38 +000013530
oliver@apple.com827d2cf2013-07-25 04:04:45 +000013531 value = m_doubleValues.get(node);
fpizlo@apple.com7e2b5292014-09-20 21:52:14 +000013532 if (isValid(value))
basile_clement@apple.com3ed5a3a2015-09-04 18:24:38 +000013533 return exitArgument(arguments, DataFormatDouble, value.value());
oliver@apple.com32295c12013-07-25 03:59:06 +000013534
msaboff@apple.com044ba8d2015-02-18 23:52:16 +000013535 DFG_CRASH(m_graph, m_node, toCString("Cannot find value for node: ", node).data());
dbatyai.u-szeged@partner.samsung.comb107a6e2014-10-21 10:18:13 +000013536 return ExitValue::dead();
oliver@apple.comea771492013-07-25 03:58:38 +000013537 }
msaboff@apple.comcdd479b2015-09-30 22:28:08 +000013538
sbarati@apple.comc13003f2015-11-10 20:42:32 +000013539 ExitValue exitArgument(StackmapArgumentList& arguments, DataFormat format, LValue value)
oliver@apple.comea771492013-07-25 03:58:38 +000013540 {
fpizlo@apple.com7e2b5292014-09-20 21:52:14 +000013541 ExitValue result = ExitValue::exitArgument(ExitArgument(format, arguments.size()));
oliver@apple.comea771492013-07-25 03:58:38 +000013542 arguments.append(value);
fpizlo@apple.com7e2b5292014-09-20 21:52:14 +000013543 return result;
oliver@apple.comea771492013-07-25 03:58:38 +000013544 }
msaboff@apple.comcdd479b2015-09-30 22:28:08 +000013545
sbarati@apple.comc13003f2015-11-10 20:42:32 +000013546 ExitValue exitValueForTailCall(StackmapArgumentList& arguments, Node* node)
msaboff@apple.comcdd479b2015-09-30 22:28:08 +000013547 {
13548 ASSERT(node->shouldGenerate());
13549 ASSERT(node->hasResult());
13550
13551 switch (node->op()) {
13552 case JSConstant:
13553 case Int52Constant:
13554 case DoubleConstant:
13555 return ExitValue::constant(node->asJSValue());
13556
13557 default:
13558 break;
13559 }
13560
13561 LoweredNodeValue value = m_jsValueValues.get(node);
13562 if (isValid(value))
13563 return exitArgument(arguments, DataFormatJS, value.value());
13564
13565 value = m_int32Values.get(node);
13566 if (isValid(value))
msaboff@apple.come317e0f2015-10-27 17:48:51 +000013567 return exitArgument(arguments, DataFormatJS, boxInt32(value.value()));
msaboff@apple.comcdd479b2015-09-30 22:28:08 +000013568
13569 value = m_booleanValues.get(node);
msaboff@apple.come317e0f2015-10-27 17:48:51 +000013570 if (isValid(value))
13571 return exitArgument(arguments, DataFormatJS, boxBoolean(value.value()));
msaboff@apple.comcdd479b2015-09-30 22:28:08 +000013572
13573 // Doubles and Int52 have been converted by ValueRep()
13574 DFG_CRASH(m_graph, m_node, toCString("Cannot find value for node: ", node).data());
13575 }
msaboff@apple.com95894332014-01-29 19:18:54 +000013576
13577 void addAvailableRecovery(
basile_clement@apple.com3ed5a3a2015-09-04 18:24:38 +000013578 Node* node, RecoveryOpcode opcode, LValue left, LValue right, DataFormat format)
msaboff@apple.com95894332014-01-29 19:18:54 +000013579 {
13580 m_availableRecoveries.append(AvailableRecovery(node, opcode, left, right, format));
13581 }
13582
13583 void addAvailableRecovery(
basile_clement@apple.com3ed5a3a2015-09-04 18:24:38 +000013584 Edge edge, RecoveryOpcode opcode, LValue left, LValue right, DataFormat format)
msaboff@apple.com95894332014-01-29 19:18:54 +000013585 {
13586 addAvailableRecovery(edge.node(), opcode, left, right, format);
13587 }
13588
oliver@apple.com827d2cf2013-07-25 04:04:45 +000013589 void setInt32(Node* node, LValue value)
13590 {
13591 m_int32Values.set(node, LoweredNodeValue(value, m_highBlock));
13592 }
fpizlo@apple.com6921b292013-09-18 17:14:02 +000013593 void setInt52(Node* node, LValue value)
13594 {
13595 m_int52Values.set(node, LoweredNodeValue(value, m_highBlock));
13596 }
13597 void setStrictInt52(Node* node, LValue value)
13598 {
13599 m_strictInt52Values.set(node, LoweredNodeValue(value, m_highBlock));
13600 }
13601 void setInt52(Node* node, LValue value, Int52Kind kind)
13602 {
13603 switch (kind) {
13604 case Int52:
13605 setInt52(node, value);
13606 return;
13607
13608 case StrictInt52:
13609 setStrictInt52(node, value);
13610 return;
13611 }
13612
msaboff@apple.com044ba8d2015-02-18 23:52:16 +000013613 DFG_CRASH(m_graph, m_node, "Corrupt int52 kind");
fpizlo@apple.com6921b292013-09-18 17:14:02 +000013614 }
oliver@apple.com827d2cf2013-07-25 04:04:45 +000013615 void setJSValue(Node* node, LValue value)
13616 {
13617 m_jsValueValues.set(node, LoweredNodeValue(value, m_highBlock));
13618 }
13619 void setBoolean(Node* node, LValue value)
13620 {
13621 m_booleanValues.set(node, LoweredNodeValue(value, m_highBlock));
13622 }
13623 void setStorage(Node* node, LValue value)
13624 {
13625 m_storageValues.set(node, LoweredNodeValue(value, m_highBlock));
13626 }
sbarati@apple.com21fc86e2016-09-06 23:22:01 +000013627 void setMapBucket(Node* node, LValue value)
13628 {
13629 m_mapBucketValues.set(node, LoweredNodeValue(value, m_highBlock));
13630 }
oliver@apple.com827d2cf2013-07-25 04:04:45 +000013631 void setDouble(Node* node, LValue value)
13632 {
13633 m_doubleValues.set(node, LoweredNodeValue(value, m_highBlock));
13634 }
13635
13636 void setInt32(LValue value)
13637 {
13638 setInt32(m_node, value);
13639 }
fpizlo@apple.com6921b292013-09-18 17:14:02 +000013640 void setInt52(LValue value)
13641 {
13642 setInt52(m_node, value);
13643 }
13644 void setStrictInt52(LValue value)
13645 {
13646 setStrictInt52(m_node, value);
13647 }
13648 void setInt52(LValue value, Int52Kind kind)
13649 {
13650 setInt52(m_node, value, kind);
13651 }
oliver@apple.com827d2cf2013-07-25 04:04:45 +000013652 void setJSValue(LValue value)
13653 {
13654 setJSValue(m_node, value);
13655 }
13656 void setBoolean(LValue value)
13657 {
13658 setBoolean(m_node, value);
13659 }
13660 void setStorage(LValue value)
13661 {
13662 setStorage(m_node, value);
13663 }
sbarati@apple.com21fc86e2016-09-06 23:22:01 +000013664 void setMapBucket(LValue value)
13665 {
13666 setMapBucket(m_node, value);
13667 }
oliver@apple.com827d2cf2013-07-25 04:04:45 +000013668 void setDouble(LValue value)
13669 {
13670 setDouble(m_node, value);
13671 }
13672
13673 bool isValid(const LoweredNodeValue& value)
13674 {
13675 if (!value)
13676 return false;
fpizlo@apple.com92dbc1f2015-11-02 00:48:03 +000013677 if (!m_graph.m_dominators->dominates(value.block(), m_highBlock))
oliver@apple.com827d2cf2013-07-25 04:04:45 +000013678 return false;
13679 return true;
13680 }
13681
oliver@apple.comea771492013-07-25 03:58:38 +000013682 void addWeakReference(JSCell* target)
13683 {
fpizlo@apple.com532f1e52013-09-04 06:26:04 +000013684 m_graph.m_plan.weakReferences.addLazily(target);
oliver@apple.comea771492013-07-25 03:58:38 +000013685 }
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +000013686
13687 LValue loadStructure(LValue value)
13688 {
13689 LValue tableIndex = m_out.load32(value, m_heaps.JSCell_structureID);
fpizlo@apple.comffa534d2014-03-05 20:26:58 +000013690 LValue tableBase = m_out.loadPtr(
13691 m_out.absolute(vm().heap.structureIDTable().base()));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000013692 TypedPointer address = m_out.baseIndex(
13693 m_heaps.structureTable, tableBase, m_out.zeroExtPtr(tableIndex));
13694 return m_out.loadPtr(address);
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +000013695 }
13696
oliver@apple.comea771492013-07-25 03:58:38 +000013697 LValue weakPointer(JSCell* pointer)
13698 {
sbarati@apple.com239d20b2017-01-26 23:50:58 +000013699 // There are weird relationships in how optimized CodeBlocks
13700 // point to other CodeBlocks. We don't want to have them be
13701 // part of the weak pointer set. For example, an optimized CodeBlock
13702 // having a weak pointer to itself will cause it to get collected.
13703 RELEASE_ASSERT(!jsDynamicCast<CodeBlock*>(pointer));
13704
oliver@apple.comea771492013-07-25 03:58:38 +000013705 addWeakReference(pointer);
sbarati@apple.com239d20b2017-01-26 23:50:58 +000013706 return m_out.weakPointer(m_graph, pointer);
oliver@apple.comea771492013-07-25 03:58:38 +000013707 }
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +000013708
sbarati@apple.com239d20b2017-01-26 23:50:58 +000013709 LValue frozenPointer(FrozenValue* value)
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +000013710 {
sbarati@apple.com239d20b2017-01-26 23:50:58 +000013711 return m_out.weakPointer(value);
13712 }
13713
13714 LValue weakStructureID(RegisteredStructure structure)
13715 {
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +000013716 return m_out.constInt32(structure->id());
13717 }
oliver@apple.comea771492013-07-25 03:58:38 +000013718
sbarati@apple.com239d20b2017-01-26 23:50:58 +000013719 LValue weakStructure(RegisteredStructure structure)
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000013720 {
sbarati@apple.com239d20b2017-01-26 23:50:58 +000013721 ASSERT(!!structure.get());
13722 return m_out.weakPointer(m_graph, structure.get());
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000013723 }
13724
oliver@apple.comea771492013-07-25 03:58:38 +000013725 TypedPointer addressFor(LValue base, int operand, ptrdiff_t offset = 0)
13726 {
13727 return m_out.address(base, m_heaps.variables[operand], offset);
13728 }
13729 TypedPointer payloadFor(LValue base, int operand)
13730 {
msaboff@apple.com95894332014-01-29 19:18:54 +000013731 return addressFor(base, operand, PayloadOffset);
oliver@apple.comea771492013-07-25 03:58:38 +000013732 }
13733 TypedPointer tagFor(LValue base, int operand)
13734 {
msaboff@apple.com95894332014-01-29 19:18:54 +000013735 return addressFor(base, operand, TagOffset);
oliver@apple.comea771492013-07-25 03:58:38 +000013736 }
msaboff@apple.com95894332014-01-29 19:18:54 +000013737 TypedPointer addressFor(int operand, ptrdiff_t offset = 0)
oliver@apple.comea771492013-07-25 03:58:38 +000013738 {
msaboff@apple.com95894332014-01-29 19:18:54 +000013739 return addressFor(VirtualRegister(operand), offset);
oliver@apple.comea771492013-07-25 03:58:38 +000013740 }
msaboff@apple.com95894332014-01-29 19:18:54 +000013741 TypedPointer addressFor(VirtualRegister operand, ptrdiff_t offset = 0)
msaboff@apple.com62aa8b72013-09-26 22:53:54 +000013742 {
msaboff@apple.com95894332014-01-29 19:18:54 +000013743 if (operand.isLocal())
13744 return addressFor(m_captured, operand.offset(), offset);
13745 return addressFor(m_callFrame, operand.offset(), offset);
msaboff@apple.com62aa8b72013-09-26 22:53:54 +000013746 }
oliver@apple.comea771492013-07-25 03:58:38 +000013747 TypedPointer payloadFor(int operand)
13748 {
msaboff@apple.com95894332014-01-29 19:18:54 +000013749 return payloadFor(VirtualRegister(operand));
oliver@apple.comea771492013-07-25 03:58:38 +000013750 }
msaboff@apple.com62aa8b72013-09-26 22:53:54 +000013751 TypedPointer payloadFor(VirtualRegister operand)
13752 {
msaboff@apple.com95894332014-01-29 19:18:54 +000013753 return addressFor(operand, PayloadOffset);
msaboff@apple.com62aa8b72013-09-26 22:53:54 +000013754 }
oliver@apple.comea771492013-07-25 03:58:38 +000013755 TypedPointer tagFor(int operand)
13756 {
msaboff@apple.com95894332014-01-29 19:18:54 +000013757 return tagFor(VirtualRegister(operand));
oliver@apple.comea771492013-07-25 03:58:38 +000013758 }
msaboff@apple.com62aa8b72013-09-26 22:53:54 +000013759 TypedPointer tagFor(VirtualRegister operand)
13760 {
msaboff@apple.com95894332014-01-29 19:18:54 +000013761 return addressFor(operand, TagOffset);
msaboff@apple.com62aa8b72013-09-26 22:53:54 +000013762 }
oliver@apple.comea771492013-07-25 03:58:38 +000013763
fpizlo@apple.com9eb43a22015-05-02 01:59:46 +000013764 AbstractValue abstractValue(Node* node)
13765 {
13766 return m_state.forNode(node);
13767 }
13768 AbstractValue abstractValue(Edge edge)
13769 {
13770 return abstractValue(edge.node());
13771 }
13772
13773 SpeculatedType provenType(Node* node)
13774 {
13775 return abstractValue(node).m_type;
13776 }
13777 SpeculatedType provenType(Edge edge)
13778 {
13779 return provenType(edge.node());
13780 }
13781
13782 JSValue provenValue(Node* node)
13783 {
13784 return abstractValue(node).m_value;
13785 }
13786 JSValue provenValue(Edge edge)
13787 {
13788 return provenValue(edge.node());
13789 }
13790
13791 StructureAbstractValue abstractStructure(Node* node)
13792 {
13793 return abstractValue(node).m_structure;
13794 }
13795 StructureAbstractValue abstractStructure(Edge edge)
13796 {
13797 return abstractStructure(edge.node());
13798 }
13799
mark.lam@apple.comf8d86242015-11-12 00:41:12 +000013800#if ENABLE(MASM_PROBE)
13801 void probe(std::function<void (CCallHelpers::ProbeContext*)> probeFunc)
13802 {
benjamin@webkit.orgcd0cf112015-12-05 02:57:03 +000013803 UNUSED_PARAM(probeFunc);
mark.lam@apple.comf8d86242015-11-12 00:41:12 +000013804 }
13805#endif
13806
fpizlo@apple.com1617af22015-02-03 00:43:25 +000013807 void crash()
13808 {
fpizlo@apple.comd3717142016-06-27 23:26:41 +000013809 crash(m_highBlock, m_node);
fpizlo@apple.com1617af22015-02-03 00:43:25 +000013810 }
fpizlo@apple.comd3717142016-06-27 23:26:41 +000013811 void crash(DFG::BasicBlock* block, Node* node)
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +000013812 {
fpizlo@apple.comd3717142016-06-27 23:26:41 +000013813 BlockIndex blockIndex = block->index;
13814 unsigned nodeIndex = node ? node->index() : UINT_MAX;
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +000013815#if ASSERT_DISABLED
fpizlo@apple.comd3717142016-06-27 23:26:41 +000013816 m_out.patchpoint(Void)->setGenerator(
13817 [=] (CCallHelpers& jit, const StackmapGenerationParams&) {
13818 AllowMacroScratchRegisterUsage allowScratch(jit);
13819
13820 jit.move(CCallHelpers::TrustedImm32(blockIndex), GPRInfo::regT0);
13821 jit.move(CCallHelpers::TrustedImm32(nodeIndex), GPRInfo::regT1);
13822 if (node)
13823 jit.move(CCallHelpers::TrustedImm32(node->op()), GPRInfo::regT2);
13824 jit.abortWithReason(FTLCrash);
13825 });
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +000013826#else
13827 m_out.call(
fpizlo@apple.com994d4532016-07-03 19:34:55 +000013828 Void,
fpizlo@apple.com9e042cd2015-12-16 23:59:13 +000013829 m_out.constIntPtr(ftlUnreachable),
sbarati@apple.com239d20b2017-01-26 23:50:58 +000013830 // We don't want the CodeBlock to have a weak pointer to itself because
13831 // that would cause it to always get collected.
13832 m_out.constIntPtr(bitwise_cast<intptr_t>(codeBlock())), m_out.constInt32(blockIndex),
fpizlo@apple.com0728b8a2014-07-23 01:19:50 +000013833 m_out.constInt32(nodeIndex));
13834#endif
13835 m_out.unreachable();
13836 }
msaboff@apple.comab247232015-02-18 02:38:16 +000013837
fpizlo@apple.comfc70ba62014-09-26 03:59:33 +000013838 AvailabilityMap& availabilityMap() { return m_availabilityCalculator.m_availability; }
fpizlo@apple.com9e64b502014-09-16 22:18:23 +000013839
oliver@apple.comea771492013-07-25 03:58:38 +000013840 VM& vm() { return m_graph.m_vm; }
13841 CodeBlock* codeBlock() { return m_graph.m_codeBlock; }
13842
13843 Graph& m_graph;
13844 State& m_ftlState;
13845 AbstractHeapRepository m_heaps;
13846 Output m_out;
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +000013847 Procedure& m_proc;
oliver@apple.comea771492013-07-25 03:58:38 +000013848
13849 LBasicBlock m_prologue;
msaboff@apple.com95894332014-01-29 19:18:54 +000013850 LBasicBlock m_handleExceptions;
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +000013851 HashMap<DFG::BasicBlock*, LBasicBlock> m_blocks;
oliver@apple.comea771492013-07-25 03:58:38 +000013852
13853 LValue m_callFrame;
msaboff@apple.com95894332014-01-29 19:18:54 +000013854 LValue m_captured;
oliver@apple.comea771492013-07-25 03:58:38 +000013855 LValue m_tagTypeNumber;
13856 LValue m_tagMask;
13857
oliver@apple.com827d2cf2013-07-25 04:04:45 +000013858 HashMap<Node*, LoweredNodeValue> m_int32Values;
fpizlo@apple.com6921b292013-09-18 17:14:02 +000013859 HashMap<Node*, LoweredNodeValue> m_strictInt52Values;
13860 HashMap<Node*, LoweredNodeValue> m_int52Values;
oliver@apple.com827d2cf2013-07-25 04:04:45 +000013861 HashMap<Node*, LoweredNodeValue> m_jsValueValues;
13862 HashMap<Node*, LoweredNodeValue> m_booleanValues;
13863 HashMap<Node*, LoweredNodeValue> m_storageValues;
sbarati@apple.com21fc86e2016-09-06 23:22:01 +000013864 HashMap<Node*, LoweredNodeValue> m_mapBucketValues;
oliver@apple.com827d2cf2013-07-25 04:04:45 +000013865 HashMap<Node*, LoweredNodeValue> m_doubleValues;
oliver@apple.comea771492013-07-25 03:58:38 +000013866
fpizlo@apple.com3ce6ab62016-02-18 16:40:25 +000013867 // This is a bit of a hack. It prevents B3 from having to do CSE on loading of arguments.
fpizlo@apple.com064f0812015-02-16 19:27:37 +000013868 // It's nice to have these optimizations on our end because we can guarantee them a bit better.
fpizlo@apple.com3ce6ab62016-02-18 16:40:25 +000013869 // Probably also saves B3 compile time.
fpizlo@apple.com064f0812015-02-16 19:27:37 +000013870 HashMap<Node*, LValue> m_loadedArgumentValues;
13871
oliver@apple.com827d2cf2013-07-25 04:04:45 +000013872 HashMap<Node*, LValue> m_phis;
oliver@apple.comea771492013-07-25 03:58:38 +000013873
fpizlo@apple.com9e64b502014-09-16 22:18:23 +000013874 LocalOSRAvailabilityCalculator m_availabilityCalculator;
oliver@apple.comea771492013-07-25 03:58:38 +000013875
msaboff@apple.com95894332014-01-29 19:18:54 +000013876 Vector<AvailableRecovery, 3> m_availableRecoveries;
13877
oliver@apple.com55d32d92013-07-25 04:05:03 +000013878 InPlaceAbstractState m_state;
13879 AbstractInterpreter<InPlaceAbstractState> m_interpreter;
benjamin@webkit.orgec1c1562015-11-19 02:48:48 +000013880 DFG::BasicBlock* m_highBlock;
13881 DFG::BasicBlock* m_nextHighBlock;
oliver@apple.comea771492013-07-25 03:58:38 +000013882 LBasicBlock m_nextLowBlock;
fpizlo@apple.comf29186e2015-08-26 19:24:41 +000013883
13884 NodeOrigin m_origin;
oliver@apple.comea771492013-07-25 03:58:38 +000013885 unsigned m_nodeIndex;
13886 Node* m_node;
oliver@apple.comea771492013-07-25 03:58:38 +000013887};
13888
fpizlo@apple.coma61e9a82015-06-16 19:17:40 +000013889} // anonymous namespace
13890
fpizlo@apple.com3ce6ab62016-02-18 16:40:25 +000013891void lowerDFGToB3(State& state)
oliver@apple.comea771492013-07-25 03:58:38 +000013892{
fpizlo@apple.com3ce6ab62016-02-18 16:40:25 +000013893 LowerDFGToB3 lowering(state);
msaboff@apple.com044ba8d2015-02-18 23:52:16 +000013894 lowering.lower();
oliver@apple.comea771492013-07-25 03:58:38 +000013895}
13896
13897} } // namespace JSC::FTL
13898
13899#endif // ENABLE(FTL_JIT)
13900