PageRenderTime 26ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/src/ast/ast-value-factory.cc

https://gitlab.com/AnneSmile/v8
C++ | 416 lines | 313 code | 58 blank | 45 comment | 59 complexity | 20ea7e88e92117bc61f92b365d470b6b MD5 | raw file
  1. // Copyright 2014 the V8 project authors. All rights reserved.
  2. // Redistribution and use in source and binary forms, with or without
  3. // modification, are permitted provided that the following conditions are
  4. // met:
  5. //
  6. // * Redistributions of source code must retain the above copyright
  7. // notice, this list of conditions and the following disclaimer.
  8. // * Redistributions in binary form must reproduce the above
  9. // copyright notice, this list of conditions and the following
  10. // disclaimer in the documentation and/or other materials provided
  11. // with the distribution.
  12. // * Neither the name of Google Inc. nor the names of its
  13. // contributors may be used to endorse or promote products derived
  14. // from this software without specific prior written permission.
  15. //
  16. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  17. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  18. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  19. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  20. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  21. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  22. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  26. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. #include "src/ast/ast-value-factory.h"
  28. #include "src/api.h"
  29. #include "src/objects.h"
  30. #include "src/utils.h"
  31. namespace v8 {
  32. namespace internal {
  33. namespace {
  34. // For using StringToArrayIndex.
  35. class OneByteStringStream {
  36. public:
  37. explicit OneByteStringStream(Vector<const byte> lb) :
  38. literal_bytes_(lb), pos_(0) {}
  39. bool HasMore() { return pos_ < literal_bytes_.length(); }
  40. uint16_t GetNext() { return literal_bytes_[pos_++]; }
  41. private:
  42. Vector<const byte> literal_bytes_;
  43. int pos_;
  44. };
  45. } // namespace
  46. class AstRawStringInternalizationKey : public HashTableKey {
  47. public:
  48. explicit AstRawStringInternalizationKey(const AstRawString* string)
  49. : string_(string) {}
  50. bool IsMatch(Object* other) override {
  51. if (string_->is_one_byte())
  52. return String::cast(other)->IsOneByteEqualTo(string_->literal_bytes_);
  53. return String::cast(other)->IsTwoByteEqualTo(
  54. Vector<const uint16_t>::cast(string_->literal_bytes_));
  55. }
  56. uint32_t Hash() override { return string_->hash() >> Name::kHashShift; }
  57. uint32_t HashForObject(Object* key) override {
  58. return String::cast(key)->Hash();
  59. }
  60. Handle<Object> AsHandle(Isolate* isolate) override {
  61. if (string_->is_one_byte())
  62. return isolate->factory()->NewOneByteInternalizedString(
  63. string_->literal_bytes_, string_->hash());
  64. return isolate->factory()->NewTwoByteInternalizedString(
  65. Vector<const uint16_t>::cast(string_->literal_bytes_), string_->hash());
  66. }
  67. private:
  68. const AstRawString* string_;
  69. };
  70. int AstString::length() const {
  71. if (IsRawStringBits::decode(bit_field_)) {
  72. return reinterpret_cast<const AstRawString*>(this)->length();
  73. }
  74. return reinterpret_cast<const AstConsString*>(this)->length();
  75. }
  76. void AstString::Internalize(Isolate* isolate) {
  77. if (IsRawStringBits::decode(bit_field_)) {
  78. return reinterpret_cast<AstRawString*>(this)->Internalize(isolate);
  79. }
  80. return reinterpret_cast<AstConsString*>(this)->Internalize(isolate);
  81. }
  82. void AstRawString::Internalize(Isolate* isolate) {
  83. if (literal_bytes_.length() == 0) {
  84. string_ = isolate->factory()->empty_string();
  85. } else {
  86. AstRawStringInternalizationKey key(this);
  87. string_ = StringTable::LookupKey(isolate, &key);
  88. }
  89. }
  90. bool AstRawString::AsArrayIndex(uint32_t* index) const {
  91. // The StringHasher will set up the hash in such a way that we can use it to
  92. // figure out whether the string is convertible to an array index.
  93. if ((hash_ & Name::kIsNotArrayIndexMask) != 0) return false;
  94. if (length() <= Name::kMaxCachedArrayIndexLength) {
  95. *index = Name::ArrayIndexValueBits::decode(hash_);
  96. } else {
  97. OneByteStringStream stream(literal_bytes_);
  98. CHECK(StringToArrayIndex(&stream, index));
  99. }
  100. return true;
  101. }
  102. bool AstRawString::IsOneByteEqualTo(const char* data) const {
  103. int length = static_cast<int>(strlen(data));
  104. if (is_one_byte() && literal_bytes_.length() == length) {
  105. const char* token = reinterpret_cast<const char*>(literal_bytes_.start());
  106. return !strncmp(token, data, length);
  107. }
  108. return false;
  109. }
  110. void AstConsString::Internalize(Isolate* isolate) {
  111. // AstRawStrings are internalized before AstConsStrings so left and right are
  112. // already internalized.
  113. string_ = isolate->factory()
  114. ->NewConsString(left_->string(), right_->string())
  115. .ToHandleChecked();
  116. }
  117. bool AstValue::IsPropertyName() const {
  118. if (type_ == STRING) {
  119. uint32_t index;
  120. return !string_->AsArrayIndex(&index);
  121. }
  122. return false;
  123. }
  124. bool AstValue::BooleanValue() const {
  125. switch (type_) {
  126. case STRING:
  127. DCHECK(string_ != NULL);
  128. return !string_->IsEmpty();
  129. case SYMBOL:
  130. UNREACHABLE();
  131. break;
  132. case NUMBER_WITH_DOT:
  133. case NUMBER:
  134. return DoubleToBoolean(number_);
  135. case SMI_WITH_DOT:
  136. case SMI:
  137. return smi_ != 0;
  138. case BOOLEAN:
  139. return bool_;
  140. case NULL_TYPE:
  141. return false;
  142. case THE_HOLE:
  143. UNREACHABLE();
  144. break;
  145. case UNDEFINED:
  146. return false;
  147. }
  148. UNREACHABLE();
  149. return false;
  150. }
  151. void AstValue::Internalize(Isolate* isolate) {
  152. switch (type_) {
  153. case STRING:
  154. DCHECK(string_ != NULL);
  155. // Strings are already internalized.
  156. DCHECK(!string_->string().is_null());
  157. break;
  158. case SYMBOL:
  159. if (symbol_name_[0] == 'i') {
  160. DCHECK_EQ(0, strcmp(symbol_name_, "iterator_symbol"));
  161. value_ = isolate->factory()->iterator_symbol();
  162. } else if (strcmp(symbol_name_, "hasInstance_symbol") == 0) {
  163. value_ = isolate->factory()->has_instance_symbol();
  164. } else {
  165. DCHECK_EQ(0, strcmp(symbol_name_, "home_object_symbol"));
  166. value_ = isolate->factory()->home_object_symbol();
  167. }
  168. break;
  169. case NUMBER_WITH_DOT:
  170. case NUMBER:
  171. value_ = isolate->factory()->NewNumber(number_, TENURED);
  172. break;
  173. case SMI_WITH_DOT:
  174. case SMI:
  175. value_ = handle(Smi::FromInt(smi_), isolate);
  176. break;
  177. case BOOLEAN:
  178. if (bool_) {
  179. value_ = isolate->factory()->true_value();
  180. } else {
  181. value_ = isolate->factory()->false_value();
  182. }
  183. break;
  184. case NULL_TYPE:
  185. value_ = isolate->factory()->null_value();
  186. break;
  187. case THE_HOLE:
  188. value_ = isolate->factory()->the_hole_value();
  189. break;
  190. case UNDEFINED:
  191. value_ = isolate->factory()->undefined_value();
  192. break;
  193. }
  194. }
  195. AstRawString* AstValueFactory::GetOneByteStringInternal(
  196. Vector<const uint8_t> literal) {
  197. uint32_t hash = StringHasher::HashSequentialString<uint8_t>(
  198. literal.start(), literal.length(), hash_seed_);
  199. return GetString(hash, true, literal);
  200. }
  201. AstRawString* AstValueFactory::GetTwoByteStringInternal(
  202. Vector<const uint16_t> literal) {
  203. uint32_t hash = StringHasher::HashSequentialString<uint16_t>(
  204. literal.start(), literal.length(), hash_seed_);
  205. return GetString(hash, false, Vector<const byte>::cast(literal));
  206. }
  207. const AstRawString* AstValueFactory::GetString(Handle<String> literal) {
  208. // For the FlatContent to stay valid, we shouldn't do any heap
  209. // allocation. Make sure we won't try to internalize the string in GetString.
  210. AstRawString* result = NULL;
  211. Isolate* saved_isolate = isolate_;
  212. isolate_ = NULL;
  213. {
  214. DisallowHeapAllocation no_gc;
  215. String::FlatContent content = literal->GetFlatContent();
  216. if (content.IsOneByte()) {
  217. result = GetOneByteStringInternal(content.ToOneByteVector());
  218. } else {
  219. DCHECK(content.IsTwoByte());
  220. result = GetTwoByteStringInternal(content.ToUC16Vector());
  221. }
  222. }
  223. isolate_ = saved_isolate;
  224. if (strings_ != nullptr && isolate_) {
  225. // Only the string we are creating is uninternalized at this point.
  226. DCHECK_EQ(result, strings_);
  227. DCHECK_NULL(strings_->next());
  228. result->Internalize(isolate_);
  229. ResetStrings();
  230. }
  231. return result;
  232. }
  233. const AstConsString* AstValueFactory::NewConsString(
  234. const AstString* left, const AstString* right) {
  235. // This Vector will be valid as long as the Collector is alive (meaning that
  236. // the AstRawString will not be moved).
  237. AstConsString* new_string = new (zone_) AstConsString(left, right);
  238. CHECK(new_string != nullptr);
  239. AddString(new_string);
  240. return new_string;
  241. }
  242. void AstValueFactory::Internalize(Isolate* isolate) {
  243. if (isolate_) {
  244. DCHECK_NULL(strings_);
  245. DCHECK_NULL(values_);
  246. // Everything is already internalized.
  247. return;
  248. }
  249. // Strings need to be internalized before values, because values refer to
  250. // strings.
  251. for (AstString* current = strings_; current != nullptr;) {
  252. AstString* next = current->next();
  253. current->Internalize(isolate);
  254. current = next;
  255. }
  256. for (AstValue* current = values_; current != nullptr;) {
  257. AstValue* next = current->next();
  258. current->Internalize(isolate);
  259. current = next;
  260. }
  261. isolate_ = isolate;
  262. ResetStrings();
  263. values_ = nullptr;
  264. }
  265. const AstValue* AstValueFactory::NewString(const AstRawString* string) {
  266. AstValue* value = new (zone_) AstValue(string);
  267. CHECK(string != nullptr);
  268. return AddValue(value);
  269. }
  270. const AstValue* AstValueFactory::NewSymbol(const char* name) {
  271. AstValue* value = new (zone_) AstValue(name);
  272. return AddValue(value);
  273. }
  274. const AstValue* AstValueFactory::NewNumber(double number, bool with_dot) {
  275. AstValue* value = new (zone_) AstValue(number, with_dot);
  276. return AddValue(value);
  277. }
  278. const AstValue* AstValueFactory::NewSmi(int number) {
  279. AstValue* value =
  280. new (zone_) AstValue(AstValue::SMI, number);
  281. return AddValue(value);
  282. }
  283. #define GENERATE_VALUE_GETTER(value, initializer) \
  284. if (!value) { \
  285. value = AddValue(new (zone_) AstValue(initializer)); \
  286. } \
  287. return value;
  288. const AstValue* AstValueFactory::NewBoolean(bool b) {
  289. if (b) {
  290. GENERATE_VALUE_GETTER(true_value_, true);
  291. } else {
  292. GENERATE_VALUE_GETTER(false_value_, false);
  293. }
  294. }
  295. const AstValue* AstValueFactory::NewNull() {
  296. GENERATE_VALUE_GETTER(null_value_, AstValue::NULL_TYPE);
  297. }
  298. const AstValue* AstValueFactory::NewUndefined() {
  299. GENERATE_VALUE_GETTER(undefined_value_, AstValue::UNDEFINED);
  300. }
  301. const AstValue* AstValueFactory::NewTheHole() {
  302. GENERATE_VALUE_GETTER(the_hole_value_, AstValue::THE_HOLE);
  303. }
  304. #undef GENERATE_VALUE_GETTER
  305. AstRawString* AstValueFactory::GetString(uint32_t hash, bool is_one_byte,
  306. Vector<const byte> literal_bytes) {
  307. // literal_bytes here points to whatever the user passed, and this is OK
  308. // because we use vector_compare (which checks the contents) to compare
  309. // against the AstRawStrings which are in the string_table_. We should not
  310. // return this AstRawString.
  311. AstRawString key(is_one_byte, literal_bytes, hash);
  312. base::HashMap::Entry* entry = string_table_.LookupOrInsert(&key, hash);
  313. if (entry->value == NULL) {
  314. // Copy literal contents for later comparison.
  315. int length = literal_bytes.length();
  316. byte* new_literal_bytes = zone_->NewArray<byte>(length);
  317. memcpy(new_literal_bytes, literal_bytes.start(), length);
  318. AstRawString* new_string = new (zone_) AstRawString(
  319. is_one_byte, Vector<const byte>(new_literal_bytes, length), hash);
  320. CHECK(new_string != nullptr);
  321. entry->key = new_string;
  322. AddString(new_string);
  323. entry->value = reinterpret_cast<void*>(1);
  324. }
  325. return reinterpret_cast<AstRawString*>(entry->key);
  326. }
  327. bool AstValueFactory::AstRawStringCompare(void* a, void* b) {
  328. const AstRawString* lhs = static_cast<AstRawString*>(a);
  329. const AstRawString* rhs = static_cast<AstRawString*>(b);
  330. DCHECK_EQ(lhs->hash(), rhs->hash());
  331. if (lhs->length() != rhs->length()) return false;
  332. const unsigned char* l = lhs->raw_data();
  333. const unsigned char* r = rhs->raw_data();
  334. size_t length = rhs->length();
  335. if (lhs->is_one_byte()) {
  336. if (rhs->is_one_byte()) {
  337. return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l),
  338. reinterpret_cast<const uint8_t*>(r),
  339. length) == 0;
  340. } else {
  341. return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(l),
  342. reinterpret_cast<const uint16_t*>(r),
  343. length) == 0;
  344. }
  345. } else {
  346. if (rhs->is_one_byte()) {
  347. return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(l),
  348. reinterpret_cast<const uint8_t*>(r),
  349. length) == 0;
  350. } else {
  351. return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(l),
  352. reinterpret_cast<const uint16_t*>(r),
  353. length) == 0;
  354. }
  355. }
  356. }
  357. } // namespace internal
  358. } // namespace v8