Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(48)

Side by Side Diff: src/ast.cc

Issue 6529032: Merge 6168:6800 from bleeding_edge to experimental/gc branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ast.h ('k') | src/bignum.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 14 matching lines...) Expand all
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "ast.h" 30 #include "ast.h"
31 #include "jump-target-inl.h" 31 #include "jump-target-inl.h"
32 #include "parser.h" 32 #include "parser.h"
33 #include "scopes.h" 33 #include "scopes.h"
34 #include "string-stream.h" 34 #include "string-stream.h"
35 #include "stub-cache.h"
36 35
37 namespace v8 { 36 namespace v8 {
38 namespace internal { 37 namespace internal {
39 38
40 unsigned AstNode::current_id_ = 0; 39 unsigned AstNode::current_id_ = 0;
41 unsigned AstNode::count_ = 0; 40 unsigned AstNode::count_ = 0;
42 VariableProxySentinel VariableProxySentinel::this_proxy_(true); 41 VariableProxySentinel VariableProxySentinel::this_proxy_(true);
43 VariableProxySentinel VariableProxySentinel::identifier_proxy_(false); 42 VariableProxySentinel VariableProxySentinel::identifier_proxy_(false);
44 ValidLeftHandSideSentinel ValidLeftHandSideSentinel::instance_; 43 ValidLeftHandSideSentinel ValidLeftHandSideSentinel::instance_;
45 Property Property::this_property_(VariableProxySentinel::this_proxy(), NULL, 0); 44 Property Property::this_property_(VariableProxySentinel::this_proxy(), NULL, 0);
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 } 158 }
160 return Token::ILLEGAL; 159 return Token::ILLEGAL;
161 } 160 }
162 161
163 162
164 bool FunctionLiteral::AllowsLazyCompilation() { 163 bool FunctionLiteral::AllowsLazyCompilation() {
165 return scope()->AllowsLazyCompilation(); 164 return scope()->AllowsLazyCompilation();
166 } 165 }
167 166
168 167
169 bool FunctionLiteral::AllowOptimize() {
170 // We can't deal with heap-allocated locals.
171 return scope()->num_heap_slots() == 0;
172 }
173
174
175 ObjectLiteral::Property::Property(Literal* key, Expression* value) { 168 ObjectLiteral::Property::Property(Literal* key, Expression* value) {
176 emit_store_ = true; 169 emit_store_ = true;
177 key_ = key; 170 key_ = key;
178 value_ = value; 171 value_ = value;
179 Object* k = *key->handle(); 172 Object* k = *key->handle();
180 if (k->IsSymbol() && Heap::Proto_symbol()->Equals(String::cast(k))) { 173 if (k->IsSymbol() && Heap::Proto_symbol()->Equals(String::cast(k))) {
181 kind_ = PROTOTYPE; 174 kind_ = PROTOTYPE;
182 } else if (value_->AsMaterializedLiteral() != NULL) { 175 } else if (value_->AsMaterializedLiteral() != NULL) {
183 kind_ = MATERIALIZED_LITERAL; 176 kind_ = MATERIALIZED_LITERAL;
184 } else if (value_->AsLiteral() != NULL) { 177 } else if (value_->AsLiteral() != NULL) {
(...skipping 23 matching lines...) Expand all
208 emit_store_ = emit_store; 201 emit_store_ = emit_store;
209 } 202 }
210 203
211 204
212 bool ObjectLiteral::Property::emit_store() { 205 bool ObjectLiteral::Property::emit_store() {
213 return emit_store_; 206 return emit_store_;
214 } 207 }
215 208
216 209
217 bool IsEqualString(void* first, void* second) { 210 bool IsEqualString(void* first, void* second) {
211 ASSERT((*reinterpret_cast<String**>(first))->IsString());
212 ASSERT((*reinterpret_cast<String**>(second))->IsString());
218 Handle<String> h1(reinterpret_cast<String**>(first)); 213 Handle<String> h1(reinterpret_cast<String**>(first));
219 Handle<String> h2(reinterpret_cast<String**>(second)); 214 Handle<String> h2(reinterpret_cast<String**>(second));
220 return (*h1)->Equals(*h2); 215 return (*h1)->Equals(*h2);
221 } 216 }
222 217
223 bool IsEqualSmi(void* first, void* second) { 218
224 Handle<Smi> h1(reinterpret_cast<Smi**>(first)); 219 bool IsEqualNumber(void* first, void* second) {
225 Handle<Smi> h2(reinterpret_cast<Smi**>(second)); 220 ASSERT((*reinterpret_cast<Object**>(first))->IsNumber());
226 return (*h1)->value() == (*h2)->value(); 221 ASSERT((*reinterpret_cast<Object**>(second))->IsNumber());
222
223 Handle<Object> h1(reinterpret_cast<Object**>(first));
224 Handle<Object> h2(reinterpret_cast<Object**>(second));
225 if (h1->IsSmi()) {
226 return h2->IsSmi() && *h1 == *h2;
227 }
228 if (h2->IsSmi()) return false;
229 Handle<HeapNumber> n1 = Handle<HeapNumber>::cast(h1);
230 Handle<HeapNumber> n2 = Handle<HeapNumber>::cast(h2);
231 ASSERT(isfinite(n1->value()));
232 ASSERT(isfinite(n2->value()));
233 return n1->value() == n2->value();
227 } 234 }
228 235
236
229 void ObjectLiteral::CalculateEmitStore() { 237 void ObjectLiteral::CalculateEmitStore() {
230 HashMap properties(&IsEqualString); 238 HashMap properties(&IsEqualString);
231 HashMap elements(&IsEqualSmi); 239 HashMap elements(&IsEqualNumber);
232 for (int i = this->properties()->length() - 1; i >= 0; i--) { 240 for (int i = this->properties()->length() - 1; i >= 0; i--) {
233 ObjectLiteral::Property* property = this->properties()->at(i); 241 ObjectLiteral::Property* property = this->properties()->at(i);
234 Literal* literal = property->key(); 242 Literal* literal = property->key();
235 Handle<Object> handle = literal->handle(); 243 Handle<Object> handle = literal->handle();
236 244
237 if (handle->IsNull()) { 245 if (handle->IsNull()) {
238 continue; 246 continue;
239 } 247 }
240 248
241 uint32_t hash; 249 uint32_t hash;
242 HashMap* table; 250 HashMap* table;
243 void* key; 251 void* key;
244 uint32_t index;
245 if (handle->IsSymbol()) { 252 if (handle->IsSymbol()) {
246 Handle<String> name(String::cast(*handle)); 253 Handle<String> name(String::cast(*handle));
247 ASSERT(!name->AsArrayIndex(&index)); 254 if (name->AsArrayIndex(&hash)) {
248 key = name.location(); 255 Handle<Object> key_handle = Factory::NewNumberFromUint(hash);
249 hash = name->Hash(); 256 key = key_handle.location();
250 table = &properties; 257 table = &elements;
251 } else if (handle->ToArrayIndex(&index)) { 258 } else {
259 key = name.location();
260 hash = name->Hash();
261 table = &properties;
262 }
263 } else if (handle->ToArrayIndex(&hash)) {
252 key = handle.location(); 264 key = handle.location();
253 hash = index;
254 table = &elements; 265 table = &elements;
255 } else { 266 } else {
256 ASSERT(handle->IsNumber()); 267 ASSERT(handle->IsNumber());
257 double num = handle->Number(); 268 double num = handle->Number();
258 char arr[100]; 269 char arr[100];
259 Vector<char> buffer(arr, ARRAY_SIZE(arr)); 270 Vector<char> buffer(arr, ARRAY_SIZE(arr));
260 const char* str = DoubleToCString(num, buffer); 271 const char* str = DoubleToCString(num, buffer);
261 Handle<String> name = Factory::NewStringFromAscii(CStrVector(str)); 272 Handle<String> name = Factory::NewStringFromAscii(CStrVector(str));
262 key = name.location(); 273 key = name.location();
263 hash = name->Hash(); 274 hash = name->Hash();
264 table = &properties; 275 table = &properties;
265 } 276 }
266 // If the key of a computed property is in the table, do not emit 277 // If the key of a computed property is in the table, do not emit
267 // a store for the property later. 278 // a store for the property later.
268 if (property->kind() == ObjectLiteral::Property::COMPUTED) { 279 if (property->kind() == ObjectLiteral::Property::COMPUTED) {
269 if (table->Lookup(literal, hash, false) != NULL) { 280 if (table->Lookup(key, hash, false) != NULL) {
270 property->set_emit_store(false); 281 property->set_emit_store(false);
271 } 282 }
272 } 283 }
273 // Add key to the table. 284 // Add key to the table.
274 table->Lookup(literal, hash, true); 285 table->Lookup(key, hash, true);
275 } 286 }
276 } 287 }
277 288
278 289
279 void TargetCollector::AddTarget(BreakTarget* target) { 290 void TargetCollector::AddTarget(BreakTarget* target) {
280 // Add the label to the collector, but discard duplicates. 291 // Add the label to the collector, but discard duplicates.
281 int length = targets_->length(); 292 int length = targets_->length();
282 for (int i = 0; i < length; i++) { 293 for (int i = 0; i < length; i++) {
283 if (targets_->at(i) == target) return; 294 if (targets_->at(i) == target) return;
284 } 295 }
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 521
511 // ---------------------------------------------------------------------------- 522 // ----------------------------------------------------------------------------
512 // Recording of type feedback 523 // Recording of type feedback
513 524
514 void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) { 525 void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
515 // Record type feedback from the oracle in the AST. 526 // Record type feedback from the oracle in the AST.
516 is_monomorphic_ = oracle->LoadIsMonomorphic(this); 527 is_monomorphic_ = oracle->LoadIsMonomorphic(this);
517 if (key()->IsPropertyName()) { 528 if (key()->IsPropertyName()) {
518 if (oracle->LoadIsBuiltin(this, Builtins::LoadIC_ArrayLength)) { 529 if (oracle->LoadIsBuiltin(this, Builtins::LoadIC_ArrayLength)) {
519 is_array_length_ = true; 530 is_array_length_ = true;
531 } else if (oracle->LoadIsBuiltin(this, Builtins::LoadIC_StringLength)) {
532 is_string_length_ = true;
520 } else if (oracle->LoadIsBuiltin(this, 533 } else if (oracle->LoadIsBuiltin(this,
521 Builtins::LoadIC_FunctionPrototype)) { 534 Builtins::LoadIC_FunctionPrototype)) {
522 is_function_prototype_ = true; 535 is_function_prototype_ = true;
523 } else { 536 } else {
524 Literal* lit_key = key()->AsLiteral(); 537 Literal* lit_key = key()->AsLiteral();
525 ASSERT(lit_key != NULL && lit_key->handle()->IsString()); 538 ASSERT(lit_key != NULL && lit_key->handle()->IsString());
526 Handle<String> name = Handle<String>::cast(lit_key->handle()); 539 Handle<String> name = Handle<String>::cast(lit_key->handle());
527 ZoneMapList* types = oracle->LoadReceiverTypes(this, name); 540 ZoneMapList* types = oracle->LoadReceiverTypes(this, name);
528 receiver_types_ = types; 541 receiver_types_ = types;
529 } 542 }
(...skipping 25 matching lines...) Expand all
555 if (info.IsSmi()) { 568 if (info.IsSmi()) {
556 compare_type_ = SMI_ONLY; 569 compare_type_ = SMI_ONLY;
557 } else if (info.IsNonPrimitive()) { 570 } else if (info.IsNonPrimitive()) {
558 compare_type_ = OBJECT_ONLY; 571 compare_type_ = OBJECT_ONLY;
559 } else { 572 } else {
560 ASSERT(compare_type_ == NONE); 573 ASSERT(compare_type_ == NONE);
561 } 574 }
562 } 575 }
563 576
564 577
565 static bool CallWithoutIC(Handle<JSFunction> target, int arity) { 578 static bool CanCallWithoutIC(Handle<JSFunction> target, int arity) {
566 SharedFunctionInfo* info = target->shared(); 579 SharedFunctionInfo* info = target->shared();
567 if (target->NeedsArgumentsAdaption()) { 580 // If the number of formal parameters of the target function does
568 // If the number of formal parameters of the target function 581 // not match the number of arguments we're passing, we don't want to
569 // does not match the number of arguments we're passing, we 582 // deal with it. Otherwise, we can call it directly.
570 // don't want to deal with it. 583 return !target->NeedsArgumentsAdaption() ||
571 return info->formal_parameter_count() == arity; 584 info->formal_parameter_count() == arity;
572 } else {
573 // If the target doesn't need arguments adaption, we can call
574 // it directly, but we avoid to do so if it has a custom call
575 // generator, because that is likely to generate better code.
576 return !info->HasBuiltinFunctionId() ||
577 !CallStubCompiler::HasCustomCallGenerator(info->builtin_function_id());
578 }
579 } 585 }
580 586
581 587
582 bool Call::ComputeTarget(Handle<Map> type, Handle<String> name) { 588 bool Call::ComputeTarget(Handle<Map> type, Handle<String> name) {
583 holder_ = Handle<JSObject>::null(); 589 if (check_type_ == RECEIVER_MAP_CHECK) {
590 // For primitive checks the holder is set up to point to the
591 // corresponding prototype object, i.e. one step of the algorithm
592 // below has been already performed.
593 // For non-primitive checks we clear it to allow computing targets
594 // for polymorphic calls.
595 holder_ = Handle<JSObject>::null();
596 }
584 while (true) { 597 while (true) {
585 LookupResult lookup; 598 LookupResult lookup;
586 type->LookupInDescriptors(NULL, *name, &lookup); 599 type->LookupInDescriptors(NULL, *name, &lookup);
587 // If the function wasn't found directly in the map, we start 600 // If the function wasn't found directly in the map, we start
588 // looking upwards through the prototype chain. 601 // looking upwards through the prototype chain.
589 if (!lookup.IsFound() && type->prototype()->IsJSObject()) { 602 if (!lookup.IsFound() && type->prototype()->IsJSObject()) {
590 holder_ = Handle<JSObject>(JSObject::cast(type->prototype())); 603 holder_ = Handle<JSObject>(JSObject::cast(type->prototype()));
591 type = Handle<Map>(holder()->map()); 604 type = Handle<Map>(holder()->map());
592 } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) { 605 } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) {
593 target_ = Handle<JSFunction>(lookup.GetConstantFunctionFromMap(*type)); 606 target_ = Handle<JSFunction>(lookup.GetConstantFunctionFromMap(*type));
594 return CallWithoutIC(target_, arguments()->length()); 607 return CanCallWithoutIC(target_, arguments()->length());
595 } else { 608 } else {
596 return false; 609 return false;
597 } 610 }
598 } 611 }
599 } 612 }
600 613
601 614
602 bool Call::ComputeGlobalTarget(Handle<GlobalObject> global, 615 bool Call::ComputeGlobalTarget(Handle<GlobalObject> global,
603 Handle<String> name) { 616 Handle<String> name) {
604 target_ = Handle<JSFunction>::null(); 617 target_ = Handle<JSFunction>::null();
605 cell_ = Handle<JSGlobalPropertyCell>::null(); 618 cell_ = Handle<JSGlobalPropertyCell>::null();
606 LookupResult lookup; 619 LookupResult lookup;
607 global->Lookup(*name, &lookup); 620 global->Lookup(*name, &lookup);
608 if (lookup.IsProperty() && lookup.type() == NORMAL) { 621 if (lookup.IsProperty() &&
622 lookup.type() == NORMAL &&
623 lookup.holder() == *global) {
609 cell_ = Handle<JSGlobalPropertyCell>(global->GetPropertyCell(&lookup)); 624 cell_ = Handle<JSGlobalPropertyCell>(global->GetPropertyCell(&lookup));
610 if (cell_->value()->IsJSFunction()) { 625 if (cell_->value()->IsJSFunction()) {
611 Handle<JSFunction> candidate(JSFunction::cast(cell_->value())); 626 Handle<JSFunction> candidate(JSFunction::cast(cell_->value()));
612 // If the function is in new space we assume it's more likely to 627 // If the function is in new space we assume it's more likely to
613 // change and thus prefer the general IC code. 628 // change and thus prefer the general IC code.
614 if (!Heap::InNewSpace(*candidate) 629 if (!Heap::InNewSpace(*candidate) &&
615 && CallWithoutIC(candidate, arguments()->length())) { 630 CanCallWithoutIC(candidate, arguments()->length())) {
616 target_ = candidate; 631 target_ = candidate;
617 return true; 632 return true;
618 } 633 }
619 } 634 }
620 } 635 }
621 return false; 636 return false;
622 } 637 }
623 638
624 639
625 void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle) { 640 void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
626 Property* property = expression()->AsProperty(); 641 Property* property = expression()->AsProperty();
627 ASSERT(property != NULL); 642 ASSERT(property != NULL);
628 // Specialize for the receiver types seen at runtime. 643 // Specialize for the receiver types seen at runtime.
629 Literal* key = property->key()->AsLiteral(); 644 Literal* key = property->key()->AsLiteral();
630 ASSERT(key != NULL && key->handle()->IsString()); 645 ASSERT(key != NULL && key->handle()->IsString());
631 Handle<String> name = Handle<String>::cast(key->handle()); 646 Handle<String> name = Handle<String>::cast(key->handle());
632 receiver_types_ = oracle->CallReceiverTypes(this, name); 647 receiver_types_ = oracle->CallReceiverTypes(this, name);
633 #ifdef DEBUG 648 #ifdef DEBUG
634 if (FLAG_enable_slow_asserts) { 649 if (FLAG_enable_slow_asserts) {
635 if (receiver_types_ != NULL) { 650 if (receiver_types_ != NULL) {
636 int length = receiver_types_->length(); 651 int length = receiver_types_->length();
637 for (int i = 0; i < length; i++) { 652 for (int i = 0; i < length; i++) {
638 Handle<Map> map = receiver_types_->at(i); 653 Handle<Map> map = receiver_types_->at(i);
639 ASSERT(!map.is_null() && *map != NULL); 654 ASSERT(!map.is_null() && *map != NULL);
640 } 655 }
641 } 656 }
642 } 657 }
643 #endif 658 #endif
644 if (receiver_types_ != NULL && receiver_types_->length() > 0) { 659 is_monomorphic_ = oracle->CallIsMonomorphic(this);
645 Handle<Map> type = receiver_types_->at(0); 660 check_type_ = oracle->GetCallCheckType(this);
646 is_monomorphic_ = oracle->CallIsMonomorphic(this); 661 if (is_monomorphic_) {
647 if (is_monomorphic_) is_monomorphic_ = ComputeTarget(type, name); 662 Handle<Map> map;
663 if (receiver_types_ != NULL && receiver_types_->length() > 0) {
664 ASSERT(check_type_ == RECEIVER_MAP_CHECK);
665 map = receiver_types_->at(0);
666 } else {
667 ASSERT(check_type_ != RECEIVER_MAP_CHECK);
668 holder_ = Handle<JSObject>(
669 oracle->GetPrototypeForPrimitiveCheck(check_type_));
670 map = Handle<Map>(holder_->map());
671 }
672 is_monomorphic_ = ComputeTarget(map, name);
648 } 673 }
649 } 674 }
650 675
651 676
652 void BinaryOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
653 TypeInfo left = oracle->BinaryType(this, TypeFeedbackOracle::LEFT);
654 TypeInfo right = oracle->BinaryType(this, TypeFeedbackOracle::RIGHT);
655 is_smi_only_ = left.IsSmi() && right.IsSmi();
656 }
657
658
659 void CompareOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) { 677 void CompareOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
660 TypeInfo left = oracle->CompareType(this, TypeFeedbackOracle::LEFT); 678 TypeInfo info = oracle->CompareType(this);
661 TypeInfo right = oracle->CompareType(this, TypeFeedbackOracle::RIGHT); 679 if (info.IsSmi()) {
662 if (left.IsSmi() && right.IsSmi()) {
663 compare_type_ = SMI_ONLY; 680 compare_type_ = SMI_ONLY;
664 } else if (left.IsNonPrimitive() && right.IsNonPrimitive()) { 681 } else if (info.IsNonPrimitive()) {
665 compare_type_ = OBJECT_ONLY; 682 compare_type_ = OBJECT_ONLY;
666 } else { 683 } else {
667 ASSERT(compare_type_ == NONE); 684 ASSERT(compare_type_ == NONE);
668 } 685 }
669 } 686 }
670 687
671 688
672 // ---------------------------------------------------------------------------- 689 // ----------------------------------------------------------------------------
673 // Implementation of AstVisitor 690 // Implementation of AstVisitor
674 691
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
1041 1058
1042 CaseClause::CaseClause(Expression* label, 1059 CaseClause::CaseClause(Expression* label,
1043 ZoneList<Statement*>* statements, 1060 ZoneList<Statement*>* statements,
1044 int pos) 1061 int pos)
1045 : label_(label), 1062 : label_(label),
1046 statements_(statements), 1063 statements_(statements),
1047 position_(pos), 1064 position_(pos),
1048 compare_type_(NONE) {} 1065 compare_type_(NONE) {}
1049 1066
1050 } } // namespace v8::internal 1067 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ast.h ('k') | src/bignum.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698