1/*
2 * Copyright (C) 2015 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "DFABytecodeCompiler.h"
28
29#if ENABLE(CONTENT_EXTENSIONS)
30
31#include "ContentExtensionRule.h"
32#include "DFA.h"
33#include "DFANode.h"
34
35namespace WebCore {
36
37namespace ContentExtensions {
38
39template <typename IntType>
40inline void append(Vector<DFABytecode>& bytecode, IntType value)
41{
42 bytecode.grow(bytecode.size() + sizeof(IntType));
43 *reinterpret_cast<IntType*>(&bytecode[bytecode.size() - sizeof(IntType)]) = value;
44}
45
46inline void appendZeroes(Vector<DFABytecode>& bytecode, DFABytecodeJumpSize jumpSize)
47{
48 switch (jumpSize) {
49 case DFABytecodeJumpSize::Int8:
50 append<int8_t>(bytecode, 0); // This value will be set when linking.
51 break;
52 case DFABytecodeJumpSize::Int16:
53 append<int16_t>(bytecode, 0); // This value will be set when linking.
54 break;
55 case DFABytecodeJumpSize::Int24:
56 append<uint16_t>(bytecode, 0);
57 append<int8_t>(bytecode, 0); // These values will be set when linking.
58 break;
59 case DFABytecodeJumpSize::Int32:
60 append<int32_t>(bytecode, 0); // This value will be set when linking.
61 break;
62 }
63}
64
65template <typename IntType>
66inline void setBits(Vector<DFABytecode>& bytecode, uint32_t index, IntType value)
67{
68 RELEASE_ASSERT(index + sizeof(IntType) <= bytecode.size());
69 ASSERT_WITH_MESSAGE(!*reinterpret_cast<IntType*>(&bytecode[index]), "Right now we should only be using setBits to overwrite values that were zero as a placeholder.");
70 *reinterpret_cast<IntType*>(&bytecode[index]) = value;
71}
72
73static unsigned appendActionBytecodeSize(uint64_t action)
74{
75 if (action & ActionFlagMask)
76 return sizeof(DFABytecodeInstruction) + sizeof(uint16_t) + sizeof(uint32_t);
77 return sizeof(DFABytecodeInstruction) + sizeof(uint32_t);
78}
79
80void DFABytecodeCompiler::emitAppendAction(uint64_t action)
81{
82 // High bits are used to store flags. See compileRuleList.
83 if (action & ActionFlagMask) {
84 if (action & IfConditionFlag)
85 append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::TestFlagsAndAppendActionWithIfCondition);
86 else
87 append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::TestFlagsAndAppendAction);
88 append<uint16_t>(m_bytecode, static_cast<uint16_t>(action >> 32));
89 append<uint32_t>(m_bytecode, static_cast<uint32_t>(action));
90 } else {
91 if (action & IfConditionFlag)
92 append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::AppendActionWithIfCondition);
93 else
94 append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::AppendAction);
95 append<uint32_t>(m_bytecode, static_cast<uint32_t>(action));
96 }
97}
98
99int32_t DFABytecodeCompiler::longestPossibleJump(uint32_t instructionLocation, uint32_t sourceNodeIndex, uint32_t destinationNodeIndex)
100{
101 if (m_nodeStartOffsets[destinationNodeIndex] == std::numeric_limits<uint32_t>::max()) {
102 // Jumping to a node that hasn't been compiled yet, we don't know exactly how far forward we will need to jump,
103 // so make sure we have enough room for the worst possible case, the farthest possible jump
104 // which would be the distance if there were no compacted branches between this jump and its destination.
105 ASSERT(instructionLocation >= m_nodeStartOffsets[sourceNodeIndex]);
106 ASSERT(m_maxNodeStartOffsets[destinationNodeIndex] > m_maxNodeStartOffsets[sourceNodeIndex]);
107 ASSERT(m_nodeStartOffsets[sourceNodeIndex] != std::numeric_limits<uint32_t>::max());
108 return m_maxNodeStartOffsets[destinationNodeIndex] - m_maxNodeStartOffsets[sourceNodeIndex] - (m_nodeStartOffsets[sourceNodeIndex] - instructionLocation);
109 }
110
111 // Jumping to an already compiled node, we already know exactly where we will need to jump to.
112 ASSERT(m_nodeStartOffsets[destinationNodeIndex] <= instructionLocation);
113 return m_nodeStartOffsets[destinationNodeIndex] - instructionLocation;
114}
115
116void DFABytecodeCompiler::emitJump(uint32_t sourceNodeIndex, uint32_t destinationNodeIndex)
117{
118 uint32_t instructionLocation = m_bytecode.size();
119 uint32_t jumpLocation = instructionLocation + sizeof(uint8_t);
120 int32_t longestPossibleJumpDistance = longestPossibleJump(instructionLocation, sourceNodeIndex, destinationNodeIndex);
121 DFABytecodeJumpSize jumpSize = smallestPossibleJumpSize(longestPossibleJumpDistance);
122 append<uint8_t>(m_bytecode, static_cast<uint8_t>(DFABytecodeInstruction::Jump) | jumpSize);
123
124 m_linkRecords.append(LinkRecord({jumpSize, longestPossibleJumpDistance, instructionLocation, jumpLocation, destinationNodeIndex}));
125 appendZeroes(m_bytecode, jumpSize);
126}
127
128void DFABytecodeCompiler::emitCheckValue(uint8_t value, uint32_t sourceNodeIndex, uint32_t destinationNodeIndex, bool caseSensitive)
129{
130 uint32_t instructionLocation = m_bytecode.size();
131 uint32_t jumpLocation = instructionLocation + 2 * sizeof(uint8_t);
132 int32_t longestPossibleJumpDistance = longestPossibleJump(instructionLocation, sourceNodeIndex, destinationNodeIndex);
133 DFABytecodeJumpSize jumpSize = smallestPossibleJumpSize(longestPossibleJumpDistance);
134 DFABytecodeInstruction instruction = caseSensitive ? DFABytecodeInstruction::CheckValueCaseSensitive : DFABytecodeInstruction::CheckValueCaseInsensitive;
135 append<uint8_t>(m_bytecode, static_cast<uint8_t>(instruction) | jumpSize);
136 append<uint8_t>(m_bytecode, value);
137 m_linkRecords.append(LinkRecord({jumpSize, longestPossibleJumpDistance, instructionLocation, jumpLocation, destinationNodeIndex}));
138 appendZeroes(m_bytecode, jumpSize);
139}
140
141void DFABytecodeCompiler::emitCheckValueRange(uint8_t lowValue, uint8_t highValue, uint32_t sourceNodeIndex, uint32_t destinationNodeIndex, bool caseSensitive)
142{
143 ASSERT_WITH_MESSAGE(lowValue < highValue, "The instruction semantic impose lowValue is strictly less than highValue.");
144
145 uint32_t instructionLocation = m_bytecode.size();
146 uint32_t jumpLocation = instructionLocation + 3 * sizeof(uint8_t);
147 int32_t longestPossibleJumpDistance = longestPossibleJump(instructionLocation, sourceNodeIndex, destinationNodeIndex);
148 DFABytecodeJumpSize jumpSize = smallestPossibleJumpSize(longestPossibleJumpDistance);
149 DFABytecodeInstruction instruction = caseSensitive ? DFABytecodeInstruction::CheckValueRangeCaseSensitive : DFABytecodeInstruction::CheckValueRangeCaseInsensitive;
150 append<uint8_t>(m_bytecode, static_cast<uint8_t>(instruction) | jumpSize);
151 append<uint8_t>(m_bytecode, lowValue);
152 append<uint8_t>(m_bytecode, highValue);
153 m_linkRecords.append(LinkRecord({jumpSize, longestPossibleJumpDistance, instructionLocation, jumpLocation, destinationNodeIndex}));
154 appendZeroes(m_bytecode, jumpSize);
155}
156
157void DFABytecodeCompiler::emitTerminate()
158{
159 append<DFABytecodeInstruction>(m_bytecode, DFABytecodeInstruction::Terminate);
160}
161
162void DFABytecodeCompiler::compileNode(uint32_t index, bool root)
163{
164 unsigned startSize = m_bytecode.size();
165
166 const DFANode& node = m_dfa.nodes[index];
167 if (node.isKilled()) {
168 ASSERT(m_nodeStartOffsets[index] == std::numeric_limits<uint32_t>::max());
169 return;
170 }
171
172 // Record starting index for linking.
173 if (!root)
174 m_nodeStartOffsets[index] = m_bytecode.size();
175
176 for (uint64_t action : node.actions(m_dfa))
177 emitAppendAction(action);
178
179 // If we jump to the root, we don't want to re-add its actions to a HashSet.
180 // We know we have already added them because the root is always compiled first and we always start interpreting at the beginning.
181 if (root)
182 m_nodeStartOffsets[index] = m_bytecode.size();
183
184 compileNodeTransitions(index);
185
186 ASSERT_UNUSED(startSize, m_bytecode.size() - startSize <= compiledNodeMaxBytecodeSize(index));
187}
188
189unsigned DFABytecodeCompiler::compiledNodeMaxBytecodeSize(uint32_t index)
190{
191 const DFANode& node = m_dfa.nodes[index];
192 if (node.isKilled())
193 return 0;
194 unsigned size = 0;
195 for (uint64_t action : node.actions(m_dfa))
196 size += appendActionBytecodeSize(action);
197 size += nodeTransitionsMaxBytecodeSize(node);
198 return size;
199}
200
201DFABytecodeCompiler::JumpTable DFABytecodeCompiler::extractJumpTable(Vector<DFABytecodeCompiler::Range>& ranges, unsigned firstRange, unsigned lastRange)
202{
203 ASSERT(lastRange > firstRange);
204 ASSERT(lastRange < ranges.size());
205
206 JumpTable jumpTable;
207 jumpTable.min = ranges[firstRange].min;
208 jumpTable.max = ranges[lastRange].max;
209 jumpTable.caseSensitive = ranges[lastRange].caseSensitive;
210
211 unsigned size = lastRange - firstRange + 1;
212 jumpTable.destinations.reserveInitialCapacity(size);
213 for (unsigned i = firstRange; i <= lastRange; ++i) {
214 const Range& range = ranges[i];
215
216 ASSERT(range.caseSensitive == jumpTable.caseSensitive);
217 ASSERT(range.min == range.max);
218 ASSERT(range.min >= jumpTable.min);
219 ASSERT(range.min <= jumpTable.max);
220
221 jumpTable.destinations.uncheckedAppend(range.destination);
222 }
223
224 ranges.remove(firstRange, size);
225
226 return jumpTable;
227}
228
229DFABytecodeCompiler::Transitions DFABytecodeCompiler::transitions(const DFANode& node)
230{
231 Transitions transitions;
232
233 uint32_t destinations[128];
234 memset(destinations, 0xff, sizeof(destinations));
235 const uint32_t noDestination = std::numeric_limits<uint32_t>::max();
236
237 transitions.useFallbackTransition = node.canUseFallbackTransition(m_dfa);
238 if (transitions.useFallbackTransition)
239 transitions.fallbackTransitionTarget = node.bestFallbackTarget(m_dfa);
240
241 for (const auto& transition : node.transitions(m_dfa)) {
242 uint32_t targetNodeIndex = transition.target();
243 if (transitions.useFallbackTransition && transitions.fallbackTransitionTarget == targetNodeIndex)
244 continue;
245
246 for (uint16_t i = transition.range().first; i <= transition.range().last; ++i)
247 destinations[i] = targetNodeIndex;
248 }
249
250 Vector<Range>& ranges = transitions.ranges;
251 uint8_t rangeMin;
252 bool hasRangeMin = false;
253 for (uint8_t i = 0; i < 128; i++) {
254 if (hasRangeMin) {
255 if (destinations[i] != destinations[rangeMin]) {
256
257 // This is the end of a range. Check if it can be case insensitive.
258 uint8_t rangeMax = i - 1;
259 bool caseSensitive = true;
260 if (rangeMin >= 'A' && rangeMax <= 'Z') {
261 caseSensitive = false;
262 for (uint8_t rangeIndex = rangeMin; rangeIndex <= rangeMax; rangeIndex++) {
263 if (destinations[rangeMin] != destinations[toASCIILower(rangeIndex)]) {
264 caseSensitive = true;
265 break;
266 }
267 }
268 }
269
270 if (!caseSensitive) {
271 // If all the lower-case destinations are the same as the upper-case destinations,
272 // then they will be covered by a case-insensitive range and will not need their own range.
273 for (uint8_t rangeIndex = rangeMin; rangeIndex <= rangeMax; rangeIndex++) {
274 ASSERT(destinations[rangeMin] == destinations[toASCIILower(rangeIndex)]);
275 destinations[toASCIILower(rangeIndex)] = noDestination;
276 }
277 ranges.append(Range(toASCIILower(rangeMin), toASCIILower(rangeMax), destinations[rangeMin], caseSensitive));
278 } else
279 ranges.append(Range(rangeMin, rangeMax, destinations[rangeMin], caseSensitive));
280
281 if (destinations[i] == noDestination)
282 hasRangeMin = false;
283 else
284 rangeMin = i;
285 }
286 } else {
287 if (destinations[i] != noDestination) {
288 rangeMin = i;
289 hasRangeMin = true;
290 }
291 }
292 }
293 if (hasRangeMin) {
294 // Ranges are appended after passing the end of them.
295 // If a range goes to 127, we will have an uncommitted rangeMin because the loop does not check 128.
296 // If a range goes to 127, there will never be values higher than it, so checking for case-insensitive ranges would always fail.
297 ranges.append(Range(rangeMin, 127, destinations[rangeMin], true));
298 }
299
300 Vector<JumpTable>& jumpTables = transitions.jumpTables;
301 unsigned rangePosition = 0;
302 unsigned baseRangePosition = std::numeric_limits<unsigned>::max();
303 Range* baseRange = nullptr;
304 while (rangePosition < ranges.size()) {
305 auto& range = ranges[rangePosition];
306 if (baseRange) {
307 if (range.min != range.max
308 || baseRange->caseSensitive != range.caseSensitive
309 || ranges[rangePosition - 1].max + 1 != range.min) {
310 if (rangePosition - baseRangePosition > 1) {
311 jumpTables.append(extractJumpTable(ranges, baseRangePosition, rangePosition - 1));
312 rangePosition = baseRangePosition;
313 }
314 baseRangePosition = std::numeric_limits<unsigned>::max();
315 baseRange = nullptr;
316 }
317 } else {
318 if (range.min == range.max) {
319 baseRangePosition = rangePosition;
320 baseRange = &range;
321 }
322 }
323 ++rangePosition;
324 }
325
326 if (baseRange && ranges.size() - baseRangePosition > 1)
327 jumpTables.append(extractJumpTable(ranges, baseRangePosition, ranges.size() - 1));
328
329 return transitions;
330}
331
332unsigned DFABytecodeCompiler::checkForJumpTableMaxBytecodeSize(const JumpTable& jumpTable)
333{
334 unsigned baselineSize = sizeof(DFABytecodeInstruction::CheckValueRangeCaseInsensitive) + 2 * sizeof(uint8_t);
335 unsigned targetsSize = (jumpTable.max - jumpTable.min + 1) * sizeof(uint32_t);
336 return baselineSize + targetsSize;
337}
338
339unsigned DFABytecodeCompiler::checkForRangeMaxBytecodeSize(const Range& range)
340{
341 if (range.min == range.max)
342 return sizeof(DFABytecodeInstruction::CheckValueCaseInsensitive) + sizeof(uint8_t) + sizeof(uint32_t);
343 return sizeof(DFABytecodeInstruction::CheckValueRangeCaseInsensitive) + 2 * sizeof(uint8_t) + sizeof(uint32_t);
344}
345
346void DFABytecodeCompiler::compileJumpTable(uint32_t nodeIndex, const JumpTable& jumpTable)
347{
348 unsigned startSize = m_bytecode.size();
349 ASSERT_WITH_MESSAGE(jumpTable.max < 128, "The DFA engine only supports the ASCII alphabet.");
350 ASSERT(jumpTable.min <= jumpTable.max);
351
352 uint32_t instructionLocation = m_bytecode.size();
353 DFABytecodeJumpSize jumpSize = Int8;
354 for (uint32_t destinationNodeIndex : jumpTable.destinations) {
355 int32_t longestPossibleJumpDistance = longestPossibleJump(instructionLocation, nodeIndex, destinationNodeIndex);
356 DFABytecodeJumpSize localJumpSize = smallestPossibleJumpSize(longestPossibleJumpDistance);
357 jumpSize = std::max(jumpSize, localJumpSize);
358 }
359
360 DFABytecodeInstruction instruction = jumpTable.caseSensitive ? DFABytecodeInstruction::JumpTableCaseSensitive : DFABytecodeInstruction::JumpTableCaseInsensitive;
361 append<uint8_t>(m_bytecode, static_cast<uint8_t>(instruction) | jumpSize);
362 append<uint8_t>(m_bytecode, jumpTable.min);
363 append<uint8_t>(m_bytecode, jumpTable.max);
364
365 for (uint32_t destinationNodeIndex : jumpTable.destinations) {
366 int32_t longestPossibleJumpDistance = longestPossibleJump(instructionLocation, nodeIndex, destinationNodeIndex);
367 uint32_t jumpLocation = m_bytecode.size();
368 m_linkRecords.append(LinkRecord({jumpSize, longestPossibleJumpDistance, instructionLocation, jumpLocation, destinationNodeIndex}));
369 appendZeroes(m_bytecode, jumpSize);
370 }
371
372 ASSERT_UNUSED(startSize, m_bytecode.size() - startSize <= checkForJumpTableMaxBytecodeSize(jumpTable));
373}
374
375void DFABytecodeCompiler::compileCheckForRange(uint32_t nodeIndex, const Range& range)
376{
377 unsigned startSize = m_bytecode.size();
378 ASSERT_WITH_MESSAGE(range.max < 128, "The DFA engine only supports the ASCII alphabet.");
379 ASSERT(range.min <= range.max);
380
381 if (range.min == range.max)
382 emitCheckValue(range.min, nodeIndex, range.destination, range.caseSensitive);
383 else
384 emitCheckValueRange(range.min, range.max, nodeIndex, range.destination, range.caseSensitive);
385
386 ASSERT_UNUSED(startSize, m_bytecode.size() - startSize <= checkForRangeMaxBytecodeSize(range));
387}
388
389unsigned DFABytecodeCompiler::nodeTransitionsMaxBytecodeSize(const DFANode& node)
390{
391 unsigned size = 0;
392 Transitions nodeTransitions = transitions(node);
393 for (const auto& jumpTable : nodeTransitions.jumpTables)
394 size += checkForJumpTableMaxBytecodeSize(jumpTable);
395 for (const auto& range : nodeTransitions.ranges)
396 size += checkForRangeMaxBytecodeSize(range);
397 if (nodeTransitions.useFallbackTransition)
398 size += sizeof(DFABytecodeInstruction::Jump) + sizeof(uint32_t);
399 else
400 size += instructionSizeWithArguments(DFABytecodeInstruction::Terminate);
401 return size;
402}
403
404void DFABytecodeCompiler::compileNodeTransitions(uint32_t nodeIndex)
405{
406 const DFANode& node = m_dfa.nodes[nodeIndex];
407 unsigned startSize = m_bytecode.size();
408
409 Transitions nodeTransitions = transitions(node);
410 for (const auto& jumpTable : nodeTransitions.jumpTables)
411 compileJumpTable(nodeIndex, jumpTable);
412 for (const auto& range : nodeTransitions.ranges)
413 compileCheckForRange(nodeIndex, range);
414 if (nodeTransitions.useFallbackTransition)
415 emitJump(nodeIndex, nodeTransitions.fallbackTransitionTarget);
416 else
417 emitTerminate();
418
419 ASSERT_UNUSED(startSize, m_bytecode.size() - startSize <= nodeTransitionsMaxBytecodeSize(node));
420}
421
422void DFABytecodeCompiler::compile()
423{
424 uint32_t startLocation = m_bytecode.size();
425 append<DFAHeader>(m_bytecode, 0); // This will be set when we are finished compiling this DFA.
426
427 m_nodeStartOffsets.resize(m_dfa.nodes.size());
428 for (unsigned i = 0; i < m_dfa.nodes.size(); ++i)
429 m_nodeStartOffsets[i] = std::numeric_limits<uint32_t>::max();
430
431 // Populate m_maxNodeStartOffsets with a worst-case index of where the node would be with no branch compaction.
432 // Compacting the branches using 1-4 byte signed jump distances should only make nodes closer together than this.
433 ASSERT(m_maxNodeStartOffsets.isEmpty());
434 m_maxNodeStartOffsets.clear();
435 m_maxNodeStartOffsets.resize(m_dfa.nodes.size());
436 unsigned rootActionsSize = 0;
437 for (uint64_t action : m_dfa.nodes[m_dfa.root].actions(m_dfa))
438 rootActionsSize += appendActionBytecodeSize(action);
439 m_maxNodeStartOffsets[m_dfa.root] = sizeof(DFAHeader) + rootActionsSize;
440 unsigned nextIndex = sizeof(DFAHeader) + compiledNodeMaxBytecodeSize(m_dfa.root);
441 for (uint32_t i = 0; i < m_dfa.nodes.size(); i++) {
442 if (i != m_dfa.root) {
443 m_maxNodeStartOffsets[i] = nextIndex;
444 nextIndex += compiledNodeMaxBytecodeSize(i);
445 }
446 }
447
448 // Make sure the root is always at the beginning of the bytecode.
449 compileNode(m_dfa.root, true);
450 for (uint32_t i = 0; i < m_dfa.nodes.size(); i++) {
451 if (i != m_dfa.root)
452 compileNode(i, false);
453 }
454
455 ASSERT(m_maxNodeStartOffsets.size() == m_nodeStartOffsets.size());
456 for (unsigned i = 0; i < m_dfa.nodes.size(); ++i) {
457 if (m_nodeStartOffsets[i] != std::numeric_limits<uint32_t>::max())
458 ASSERT(m_maxNodeStartOffsets[i] >= m_nodeStartOffsets[i]);
459 }
460
461 // Link.
462 for (const auto& linkRecord : m_linkRecords) {
463 uint32_t destination = m_nodeStartOffsets[linkRecord.destinationNodeIndex];
464 RELEASE_ASSERT(destination < std::numeric_limits<int32_t>::max());
465 int32_t distance = destination - linkRecord.instructionLocation;
466 ASSERT(abs(distance) <= abs(linkRecord.longestPossibleJump));
467
468 switch (linkRecord.jumpSize) {
469 case Int8:
470 RELEASE_ASSERT(distance == static_cast<int8_t>(distance));
471 setBits<int8_t>(m_bytecode, linkRecord.jumpLocation, static_cast<int8_t>(distance));
472 break;
473 case Int16:
474 RELEASE_ASSERT(distance == static_cast<int16_t>(distance));
475 setBits<int16_t>(m_bytecode, linkRecord.jumpLocation, static_cast<int16_t>(distance));
476 break;
477 case Int24:
478 RELEASE_ASSERT(distance >= Int24Min && distance <= Int24Max);
479 setBits<uint16_t>(m_bytecode, linkRecord.jumpLocation, static_cast<uint16_t>(distance));
480 setBits<int8_t>(m_bytecode, linkRecord.jumpLocation + sizeof(int16_t), static_cast<int8_t>(distance >> 16));
481 break;
482 case Int32:
483 setBits<int32_t>(m_bytecode, linkRecord.jumpLocation, distance);
484 break;
485 }
486 }
487
488 setBits<DFAHeader>(m_bytecode, startLocation, m_bytecode.size() - startLocation);
489}
490
491} // namespace ContentExtensions
492
493} // namespace WebCore
494
495#endif // ENABLE(CONTENT_EXTENSIONS)
496