Revision f230a1cf deps/v8/src/scanner.cc
deps/v8/src/scanner.cc | ||
---|---|---|
27 | 27 |
|
28 | 28 |
// Features shared by parsing and pre-parsing scanners. |
29 | 29 |
|
30 |
#include <cmath> |
|
31 |
|
|
30 | 32 |
#include "scanner.h" |
31 | 33 |
|
32 | 34 |
#include "../include/v8stdint.h" |
33 | 35 |
#include "char-predicates-inl.h" |
36 |
#include "conversions-inl.h" |
|
37 |
#include "list-inl.h" |
|
34 | 38 |
|
35 | 39 |
namespace v8 { |
36 | 40 |
namespace internal { |
... | ... | |
1108 | 1112 |
return true; |
1109 | 1113 |
} |
1110 | 1114 |
|
1115 |
|
|
1116 |
int DuplicateFinder::AddAsciiSymbol(Vector<const char> key, int value) { |
|
1117 |
return AddSymbol(Vector<const byte>::cast(key), true, value); |
|
1118 |
} |
|
1119 |
|
|
1120 |
|
|
1121 |
int DuplicateFinder::AddUtf16Symbol(Vector<const uint16_t> key, int value) { |
|
1122 |
return AddSymbol(Vector<const byte>::cast(key), false, value); |
|
1123 |
} |
|
1124 |
|
|
1125 |
|
|
1126 |
int DuplicateFinder::AddSymbol(Vector<const byte> key, |
|
1127 |
bool is_ascii, |
|
1128 |
int value) { |
|
1129 |
uint32_t hash = Hash(key, is_ascii); |
|
1130 |
byte* encoding = BackupKey(key, is_ascii); |
|
1131 |
HashMap::Entry* entry = map_.Lookup(encoding, hash, true); |
|
1132 |
int old_value = static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); |
|
1133 |
entry->value = |
|
1134 |
reinterpret_cast<void*>(static_cast<intptr_t>(value | old_value)); |
|
1135 |
return old_value; |
|
1136 |
} |
|
1137 |
|
|
1138 |
|
|
1139 |
int DuplicateFinder::AddNumber(Vector<const char> key, int value) { |
|
1140 |
ASSERT(key.length() > 0); |
|
1141 |
// Quick check for already being in canonical form. |
|
1142 |
if (IsNumberCanonical(key)) { |
|
1143 |
return AddAsciiSymbol(key, value); |
|
1144 |
} |
|
1145 |
|
|
1146 |
int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY; |
|
1147 |
double double_value = StringToDouble(unicode_constants_, key, flags, 0.0); |
|
1148 |
int length; |
|
1149 |
const char* string; |
|
1150 |
if (!std::isfinite(double_value)) { |
|
1151 |
string = "Infinity"; |
|
1152 |
length = 8; // strlen("Infinity"); |
|
1153 |
} else { |
|
1154 |
string = DoubleToCString(double_value, |
|
1155 |
Vector<char>(number_buffer_, kBufferSize)); |
|
1156 |
length = StrLength(string); |
|
1157 |
} |
|
1158 |
return AddSymbol(Vector<const byte>(reinterpret_cast<const byte*>(string), |
|
1159 |
length), true, value); |
|
1160 |
} |
|
1161 |
|
|
1162 |
|
|
1163 |
bool DuplicateFinder::IsNumberCanonical(Vector<const char> number) { |
|
1164 |
// Test for a safe approximation of number literals that are already |
|
1165 |
// in canonical form: max 15 digits, no leading zeroes, except an |
|
1166 |
// integer part that is a single zero, and no trailing zeros below |
|
1167 |
// the decimal point. |
|
1168 |
int pos = 0; |
|
1169 |
int length = number.length(); |
|
1170 |
if (number.length() > 15) return false; |
|
1171 |
if (number[pos] == '0') { |
|
1172 |
pos++; |
|
1173 |
} else { |
|
1174 |
while (pos < length && |
|
1175 |
static_cast<unsigned>(number[pos] - '0') <= ('9' - '0')) pos++; |
|
1176 |
} |
|
1177 |
if (length == pos) return true; |
|
1178 |
if (number[pos] != '.') return false; |
|
1179 |
pos++; |
|
1180 |
bool invalid_last_digit = true; |
|
1181 |
while (pos < length) { |
|
1182 |
byte digit = number[pos] - '0'; |
|
1183 |
if (digit > '9' - '0') return false; |
|
1184 |
invalid_last_digit = (digit == 0); |
|
1185 |
pos++; |
|
1186 |
} |
|
1187 |
return !invalid_last_digit; |
|
1188 |
} |
|
1189 |
|
|
1190 |
|
|
1191 |
uint32_t DuplicateFinder::Hash(Vector<const byte> key, bool is_ascii) { |
|
1192 |
// Primitive hash function, almost identical to the one used |
|
1193 |
// for strings (except that it's seeded by the length and ASCII-ness). |
|
1194 |
int length = key.length(); |
|
1195 |
uint32_t hash = (length << 1) | (is_ascii ? 1 : 0) ; |
|
1196 |
for (int i = 0; i < length; i++) { |
|
1197 |
uint32_t c = key[i]; |
|
1198 |
hash = (hash + c) * 1025; |
|
1199 |
hash ^= (hash >> 6); |
|
1200 |
} |
|
1201 |
return hash; |
|
1202 |
} |
|
1203 |
|
|
1204 |
|
|
1205 |
bool DuplicateFinder::Match(void* first, void* second) { |
|
1206 |
// Decode lengths. |
|
1207 |
// Length + ASCII-bit is encoded as base 128, most significant heptet first, |
|
1208 |
// with a 8th bit being non-zero while there are more heptets. |
|
1209 |
// The value encodes the number of bytes following, and whether the original |
|
1210 |
// was ASCII. |
|
1211 |
byte* s1 = reinterpret_cast<byte*>(first); |
|
1212 |
byte* s2 = reinterpret_cast<byte*>(second); |
|
1213 |
uint32_t length_ascii_field = 0; |
|
1214 |
byte c1; |
|
1215 |
do { |
|
1216 |
c1 = *s1; |
|
1217 |
if (c1 != *s2) return false; |
|
1218 |
length_ascii_field = (length_ascii_field << 7) | (c1 & 0x7f); |
|
1219 |
s1++; |
|
1220 |
s2++; |
|
1221 |
} while ((c1 & 0x80) != 0); |
|
1222 |
int length = static_cast<int>(length_ascii_field >> 1); |
|
1223 |
return memcmp(s1, s2, length) == 0; |
|
1224 |
} |
|
1225 |
|
|
1226 |
|
|
1227 |
byte* DuplicateFinder::BackupKey(Vector<const byte> bytes, |
|
1228 |
bool is_ascii) { |
|
1229 |
uint32_t ascii_length = (bytes.length() << 1) | (is_ascii ? 1 : 0); |
|
1230 |
backing_store_.StartSequence(); |
|
1231 |
// Emit ascii_length as base-128 encoded number, with the 7th bit set |
|
1232 |
// on the byte of every heptet except the last, least significant, one. |
|
1233 |
if (ascii_length >= (1 << 7)) { |
|
1234 |
if (ascii_length >= (1 << 14)) { |
|
1235 |
if (ascii_length >= (1 << 21)) { |
|
1236 |
if (ascii_length >= (1 << 28)) { |
|
1237 |
backing_store_.Add(static_cast<byte>((ascii_length >> 28) | 0x80)); |
|
1238 |
} |
|
1239 |
backing_store_.Add(static_cast<byte>((ascii_length >> 21) | 0x80u)); |
|
1240 |
} |
|
1241 |
backing_store_.Add(static_cast<byte>((ascii_length >> 14) | 0x80u)); |
|
1242 |
} |
|
1243 |
backing_store_.Add(static_cast<byte>((ascii_length >> 7) | 0x80u)); |
|
1244 |
} |
|
1245 |
backing_store_.Add(static_cast<byte>(ascii_length & 0x7f)); |
|
1246 |
|
|
1247 |
backing_store_.AddBlock(bytes); |
|
1248 |
return backing_store_.EndSequence().start(); |
|
1249 |
} |
|
1250 |
|
|
1111 | 1251 |
} } // namespace v8::internal |
Also available in: Unified diff