OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "v8.h" | 5 #include "v8.h" |
6 | 6 |
7 #include "ast.h" | 7 #include "ast.h" |
| 8 #include "ast-string-table.h" |
8 #include "func-name-inferrer.h" | 9 #include "func-name-inferrer.h" |
9 #include "list-inl.h" | 10 #include "list-inl.h" |
10 | 11 |
11 namespace v8 { | 12 namespace v8 { |
12 namespace internal { | 13 namespace internal { |
13 | 14 |
14 FuncNameInferrer::FuncNameInferrer(Isolate* isolate, Zone* zone) | 15 FuncNameInferrer::FuncNameInferrer(AstStringTable* string_table, Zone* zone) |
15 : isolate_(isolate), | 16 : string_table_(string_table), |
16 entries_stack_(10, zone), | 17 entries_stack_(10, zone), |
17 names_stack_(5, zone), | 18 names_stack_(5, zone), |
18 funcs_to_infer_(4, zone), | 19 funcs_to_infer_(4, zone), |
19 zone_(zone) { | 20 zone_(zone) { |
20 } | 21 } |
21 | 22 |
22 | 23 |
23 void FuncNameInferrer::PushEnclosingName(Handle<String> name) { | 24 void FuncNameInferrer::PushEnclosingName(const AstString* name) { |
24 // Enclosing name is a name of a constructor function. To check | 25 // Enclosing name is a name of a constructor function. To check |
25 // that it is really a constructor, we check that it is not empty | 26 // that it is really a constructor, we check that it is not empty |
26 // and starts with a capital letter. | 27 // and starts with a capital letter. |
27 if (name->length() > 0 && Runtime::IsUpperCaseChar( | 28 if (name->length() > 0 && unibrow::Uppercase::Is(name->raw_data()[0])) { |
28 isolate()->runtime_state(), name->Get(0))) { | |
29 names_stack_.Add(Name(name, kEnclosingConstructorName), zone()); | 29 names_stack_.Add(Name(name, kEnclosingConstructorName), zone()); |
30 } | 30 } |
31 } | 31 } |
32 | 32 |
33 | 33 |
34 void FuncNameInferrer::PushLiteralName(Handle<String> name) { | 34 void FuncNameInferrer::PushLiteralName(const AstString* name) { |
35 if (IsOpen() && | 35 if (IsOpen() && name != string_table_->prototype_string()) { |
36 !String::Equals(isolate()->factory()->prototype_string(), name)) { | |
37 names_stack_.Add(Name(name, kLiteralName), zone()); | 36 names_stack_.Add(Name(name, kLiteralName), zone()); |
38 } | 37 } |
39 } | 38 } |
40 | 39 |
41 | 40 |
42 void FuncNameInferrer::PushVariableName(Handle<String> name) { | 41 void FuncNameInferrer::PushVariableName(const AstString* name) { |
43 if (IsOpen() && | 42 if (IsOpen() && name != string_table_->dot_result_string()) { |
44 !String::Equals(isolate()->factory()->dot_result_string(), name)) { | |
45 names_stack_.Add(Name(name, kVariableName), zone()); | 43 names_stack_.Add(Name(name, kVariableName), zone()); |
46 } | 44 } |
47 } | 45 } |
48 | 46 |
49 | 47 |
50 Handle<String> FuncNameInferrer::MakeNameFromStack() { | 48 const AstString* FuncNameInferrer::MakeNameFromStack() { |
51 return MakeNameFromStackHelper(0, isolate()->factory()->empty_string()); | 49 // First see how many names we will use. |
52 } | 50 int length = 0; |
53 | 51 bool one_byte = true; |
54 | 52 int pos = 0; |
55 Handle<String> FuncNameInferrer::MakeNameFromStackHelper(int pos, | 53 while (pos < names_stack_.length()) { |
56 Handle<String> prev) { | 54 if (pos < names_stack_.length() - 1 && |
57 if (pos >= names_stack_.length()) return prev; | 55 names_stack_.at(pos).type == kVariableName && |
58 if (pos < names_stack_.length() - 1 && | 56 names_stack_.at(pos + 1).type == kVariableName) { |
59 names_stack_.at(pos).type == kVariableName && | 57 // Skip consecutive variable declarations. |
60 names_stack_.at(pos + 1).type == kVariableName) { | 58 ++pos; |
61 // Skip consecutive variable declarations. | 59 continue; |
62 return MakeNameFromStackHelper(pos + 1, prev); | 60 } |
| 61 int cur_length = names_stack_.at(pos).name->length(); |
| 62 if (length + 1 + cur_length > String::kMaxLength) { |
| 63 break; |
| 64 } |
| 65 if (length == 0) { |
| 66 length = cur_length; |
| 67 } else { // Add the . between names. |
| 68 length += (1 + cur_length); |
| 69 } |
| 70 one_byte = one_byte && names_stack_.at(pos).name->is_one_byte(); |
| 71 ++pos; |
| 72 } |
| 73 const AstString* to_return = NULL; |
| 74 const char* dot = "."; |
| 75 if (one_byte) { |
| 76 Vector<uint8_t> new_name = Vector<uint8_t>::New(length); |
| 77 int name_pos = 0; |
| 78 for (int i = 0; i < pos; ++i) { |
| 79 if (i < names_stack_.length() - 1 && |
| 80 names_stack_.at(i).type == kVariableName && |
| 81 names_stack_.at(i + 1).type == kVariableName) { |
| 82 // Skip consecutive variable declarations. |
| 83 continue; |
| 84 } |
| 85 if (name_pos != 0) { |
| 86 CopyChars(new_name.start() + name_pos, dot, 1); |
| 87 ++name_pos; |
| 88 } |
| 89 CopyChars(new_name.start() + name_pos, |
| 90 names_stack_.at(i).name->raw_data(), |
| 91 names_stack_.at(i).name->length()); |
| 92 name_pos += names_stack_.at(i).name->length(); |
| 93 } |
| 94 to_return = string_table_->GetOneByteString(Vector<const uint8_t>( |
| 95 reinterpret_cast<const uint8_t*>(new_name.start()), |
| 96 new_name.length())); |
| 97 new_name.Dispose(); |
63 } else { | 98 } else { |
64 if (prev->length() > 0) { | 99 Vector<uint16_t> new_name = Vector<uint16_t>::New(length); |
65 Handle<String> name = names_stack_.at(pos).name; | 100 int name_pos = 0; |
66 if (prev->length() + name->length() + 1 > String::kMaxLength) return prev; | 101 for (int i = 0; i < pos; ++i) { |
67 Factory* factory = isolate()->factory(); | 102 if (i < names_stack_.length() - 1 && |
68 Handle<String> curr = | 103 names_stack_.at(i).type == kVariableName && |
69 factory->NewConsString(factory->dot_string(), name).ToHandleChecked(); | 104 names_stack_.at(i + 1).type == kVariableName) { |
70 curr = factory->NewConsString(prev, curr).ToHandleChecked(); | 105 // Skip consecutive variable declarations. |
71 return MakeNameFromStackHelper(pos + 1, curr); | 106 continue; |
72 } else { | 107 } |
73 return MakeNameFromStackHelper(pos + 1, names_stack_.at(pos).name); | 108 if (name_pos != 0) { |
| 109 CopyChars(new_name.start() + name_pos, dot, 1); |
| 110 ++name_pos; |
| 111 } |
| 112 if (names_stack_.at(i).name->is_one_byte()) { |
| 113 CopyChars(new_name.start() + name_pos, |
| 114 names_stack_.at(i).name->raw_data(), |
| 115 names_stack_.at(i).name->length()); |
| 116 } else { |
| 117 CopyChars(new_name.start() + name_pos, |
| 118 reinterpret_cast<const uint16_t*>( |
| 119 names_stack_.at(i).name->raw_data()), |
| 120 names_stack_.at(i).name->length()); |
| 121 } |
| 122 name_pos += names_stack_.at(i).name->length(); |
74 } | 123 } |
| 124 to_return = string_table_->GetTwoByteString(Vector<const uint16_t>( |
| 125 reinterpret_cast<const uint16_t*>(new_name.start()), |
| 126 new_name.length())); |
| 127 new_name.Dispose(); |
75 } | 128 } |
| 129 return to_return; |
76 } | 130 } |
77 | 131 |
78 | 132 |
79 void FuncNameInferrer::InferFunctionsNames() { | 133 void FuncNameInferrer::InferFunctionsNames() { |
80 Handle<String> func_name = MakeNameFromStack(); | 134 const AstString* func_name = MakeNameFromStack(); |
81 for (int i = 0; i < funcs_to_infer_.length(); ++i) { | 135 for (int i = 0; i < funcs_to_infer_.length(); ++i) { |
82 funcs_to_infer_[i]->set_inferred_name(func_name); | 136 funcs_to_infer_[i]->set_raw_inferred_name(func_name); |
83 } | 137 } |
84 funcs_to_infer_.Rewind(0); | 138 funcs_to_infer_.Rewind(0); |
85 } | 139 } |
86 | 140 |
87 | 141 |
88 } } // namespace v8::internal | 142 } } // namespace v8::internal |
OLD | NEW |