| OLD | NEW | 
|---|
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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 // TODO(mvstanton): Remove this define after this flag is turned on globally | 
|  | 6 #define V8_IMMINENT_DEPRECATION_WARNINGS | 
|  | 7 | 
| 5 #include "src/v8.h" | 8 #include "src/v8.h" | 
| 6 #include "test/cctest/cctest.h" | 9 #include "test/cctest/cctest.h" | 
| 7 | 10 | 
| 8 #include "src/api.h" | 11 #include "src/api.h" | 
| 9 #include "src/debug/debug.h" | 12 #include "src/debug/debug.h" | 
| 10 #include "src/execution.h" | 13 #include "src/execution.h" | 
| 11 #include "src/factory.h" | 14 #include "src/factory.h" | 
| 12 #include "src/global-handles.h" | 15 #include "src/global-handles.h" | 
| 13 #include "src/macro-assembler.h" | 16 #include "src/macro-assembler.h" | 
| 14 #include "src/objects.h" | 17 #include "src/objects.h" | 
| 15 #include "test/cctest/test-feedback-vector.h" | 18 #include "test/cctest/test-feedback-vector.h" | 
| 16 | 19 | 
| 17 using namespace v8::internal; | 20 using namespace v8::internal; | 
| 18 | 21 | 
| 19 namespace { | 22 namespace { | 
| 20 | 23 | 
| 21 #define CHECK_SLOT_KIND(helper, index, expected_kind) \ | 24 #define CHECK_SLOT_KIND(helper, index, expected_kind) \ | 
| 22   CHECK_EQ(expected_kind, helper.vector()->GetKind(helper.slot(index))); | 25   CHECK_EQ(expected_kind, helper.vector()->GetKind(helper.slot(index))); | 
| 23 | 26 | 
| 24 | 27 | 
|  | 28 static Handle<JSFunction> GetFunction(const char* name) { | 
|  | 29   v8::MaybeLocal<v8::Value> v8_f = CcTest::global()->Get( | 
|  | 30       v8::Isolate::GetCurrent()->GetCurrentContext(), v8_str(name)); | 
|  | 31   Handle<JSFunction> f = | 
|  | 32       Handle<JSFunction>::cast(v8::Utils::OpenHandle(*v8_f.ToLocalChecked())); | 
|  | 33   return f; | 
|  | 34 } | 
|  | 35 | 
|  | 36 | 
| 25 TEST(VectorStructure) { | 37 TEST(VectorStructure) { | 
| 26   LocalContext context; | 38   LocalContext context; | 
| 27   v8::HandleScope scope(context->GetIsolate()); | 39   v8::HandleScope scope(context->GetIsolate()); | 
| 28   Isolate* isolate = CcTest::i_isolate(); | 40   Isolate* isolate = CcTest::i_isolate(); | 
| 29   Factory* factory = isolate->factory(); | 41   Factory* factory = isolate->factory(); | 
| 30   Zone* zone = isolate->runtime_zone(); | 42   Zone* zone = isolate->runtime_zone(); | 
| 31 | 43 | 
| 32   // Empty vectors are the empty fixed array. | 44   // Empty vectors are the empty fixed array. | 
| 33   StaticFeedbackVectorSpec empty; | 45   StaticFeedbackVectorSpec empty; | 
| 34   Handle<TypeFeedbackVector> vector = NewTypeFeedbackVector(isolate, &empty); | 46   Handle<TypeFeedbackVector> vector = NewTypeFeedbackVector(isolate, &empty); | 
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 193   CcTest::InitializeVM(); | 205   CcTest::InitializeVM(); | 
| 194   LocalContext context; | 206   LocalContext context; | 
| 195   v8::HandleScope scope(context->GetIsolate()); | 207   v8::HandleScope scope(context->GetIsolate()); | 
| 196   Isolate* isolate = CcTest::i_isolate(); | 208   Isolate* isolate = CcTest::i_isolate(); | 
| 197   Heap* heap = isolate->heap(); | 209   Heap* heap = isolate->heap(); | 
| 198 | 210 | 
| 199   // Make sure function f has a call that uses a type feedback slot. | 211   // Make sure function f has a call that uses a type feedback slot. | 
| 200   CompileRun( | 212   CompileRun( | 
| 201       "function fun() {};" | 213       "function fun() {};" | 
| 202       "function f(a) { a(); } f(fun);"); | 214       "function f(a) { a(); } f(fun);"); | 
| 203   Handle<JSFunction> f = Handle<JSFunction>::cast(v8::Utils::OpenHandle( | 215   Handle<JSFunction> f = GetFunction("f"); | 
| 204       *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f"))))); |  | 
| 205   // There should be one IC. | 216   // There should be one IC. | 
| 206   Handle<Code> code = handle(f->shared()->code(), isolate); | 217   Handle<Code> code = handle(f->shared()->code(), isolate); | 
| 207   TypeFeedbackInfo* feedback_info = | 218   TypeFeedbackInfo* feedback_info = | 
| 208       TypeFeedbackInfo::cast(code->type_feedback_info()); | 219       TypeFeedbackInfo::cast(code->type_feedback_info()); | 
| 209   CHECK_EQ(1, feedback_info->ic_total_count()); | 220   CHECK_EQ(1, feedback_info->ic_total_count()); | 
| 210   CHECK_EQ(0, feedback_info->ic_with_type_info_count()); | 221   CHECK_EQ(0, feedback_info->ic_with_type_info_count()); | 
| 211   CHECK_EQ(0, feedback_info->ic_generic_count()); | 222   CHECK_EQ(0, feedback_info->ic_generic_count()); | 
| 212   Handle<TypeFeedbackVector> feedback_vector = | 223   Handle<TypeFeedbackVector> feedback_vector = | 
| 213       handle(f->shared()->feedback_vector(), isolate); | 224       handle(f->shared()->feedback_vector(), isolate); | 
| 214   FeedbackVectorHelper helper(feedback_vector); | 225   FeedbackVectorHelper helper(feedback_vector); | 
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 248   CcTest::InitializeVM(); | 259   CcTest::InitializeVM(); | 
| 249   LocalContext context; | 260   LocalContext context; | 
| 250   v8::HandleScope scope(context->GetIsolate()); | 261   v8::HandleScope scope(context->GetIsolate()); | 
| 251   Isolate* isolate = CcTest::i_isolate(); | 262   Isolate* isolate = CcTest::i_isolate(); | 
| 252   Heap* heap = isolate->heap(); | 263   Heap* heap = isolate->heap(); | 
| 253 | 264 | 
| 254   // Make sure function f has a call that uses a type feedback slot. | 265   // Make sure function f has a call that uses a type feedback slot. | 
| 255   CompileRun( | 266   CompileRun( | 
| 256       "function foo() { return 17; }" | 267       "function foo() { return 17; }" | 
| 257       "function f(a) { a(); } f(foo);"); | 268       "function f(a) { a(); } f(foo);"); | 
| 258   Handle<JSFunction> f = Handle<JSFunction>::cast(v8::Utils::OpenHandle( | 269   Handle<JSFunction> f = GetFunction("f"); | 
| 259       *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f"))))); |  | 
| 260   // There should be one IC. | 270   // There should be one IC. | 
| 261   Handle<TypeFeedbackVector> feedback_vector = | 271   Handle<TypeFeedbackVector> feedback_vector = | 
| 262       Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate); | 272       Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate); | 
| 263   FeedbackVectorSlot slot(0); | 273   FeedbackVectorSlot slot(0); | 
| 264   CallICNexus nexus(feedback_vector, slot); | 274   CallICNexus nexus(feedback_vector, slot); | 
| 265   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); | 275   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); | 
| 266   // CallIC doesn't return map feedback. | 276   // CallIC doesn't return map feedback. | 
| 267   CHECK(!nexus.FindFirstMap()); | 277   CHECK(!nexus.FindFirstMap()); | 
| 268 | 278 | 
| 269   CompileRun("f(function() { return 16; })"); | 279   CompileRun("f(function() { return 16; })"); | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
| 290   CcTest::InitializeVM(); | 300   CcTest::InitializeVM(); | 
| 291   LocalContext context; | 301   LocalContext context; | 
| 292   v8::HandleScope scope(context->GetIsolate()); | 302   v8::HandleScope scope(context->GetIsolate()); | 
| 293   Isolate* isolate = CcTest::i_isolate(); | 303   Isolate* isolate = CcTest::i_isolate(); | 
| 294   Heap* heap = isolate->heap(); | 304   Heap* heap = isolate->heap(); | 
| 295 | 305 | 
| 296   // Make sure function f has a call that uses a type feedback slot. | 306   // Make sure function f has a call that uses a type feedback slot. | 
| 297   CompileRun( | 307   CompileRun( | 
| 298       "var o = { foo: 3 };" | 308       "var o = { foo: 3 };" | 
| 299       "function f(a) { return a.foo; } f(o);"); | 309       "function f(a) { return a.foo; } f(o);"); | 
| 300   Handle<JSFunction> f = Handle<JSFunction>::cast(v8::Utils::OpenHandle( | 310   Handle<JSFunction> f = GetFunction("f"); | 
| 301       *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f"))))); |  | 
| 302   // There should be one IC. | 311   // There should be one IC. | 
| 303   Handle<TypeFeedbackVector> feedback_vector = | 312   Handle<TypeFeedbackVector> feedback_vector = | 
| 304       Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate); | 313       Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate); | 
| 305   FeedbackVectorSlot slot(0); | 314   FeedbackVectorSlot slot(0); | 
| 306   LoadICNexus nexus(feedback_vector, slot); | 315   LoadICNexus nexus(feedback_vector, slot); | 
| 307   CHECK_EQ(PREMONOMORPHIC, nexus.StateFromFeedback()); | 316   CHECK_EQ(PREMONOMORPHIC, nexus.StateFromFeedback()); | 
| 308 | 317 | 
| 309   CompileRun("f(o)"); | 318   CompileRun("f(o)"); | 
| 310   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); | 319   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); | 
| 311   // Verify that the monomorphic map is the one we expect. | 320   // Verify that the monomorphic map is the one we expect. | 
| 312   Handle<JSObject> o = v8::Utils::OpenHandle( | 321   v8::MaybeLocal<v8::Value> v8_o = | 
| 313       *v8::Handle<v8::Object>::Cast(CcTest::global()->Get(v8_str("o")))); | 322       CcTest::global()->Get(context.local(), v8_str("o")); | 
|  | 323   Handle<JSObject> o = | 
|  | 324       Handle<JSObject>::cast(v8::Utils::OpenHandle(*v8_o.ToLocalChecked())); | 
| 314   CHECK_EQ(o->map(), nexus.FindFirstMap()); | 325   CHECK_EQ(o->map(), nexus.FindFirstMap()); | 
| 315 | 326 | 
| 316   // Now go polymorphic. | 327   // Now go polymorphic. | 
| 317   CompileRun("f({ blarg: 3, foo: 2 })"); | 328   CompileRun("f({ blarg: 3, foo: 2 })"); | 
| 318   CHECK_EQ(POLYMORPHIC, nexus.StateFromFeedback()); | 329   CHECK_EQ(POLYMORPHIC, nexus.StateFromFeedback()); | 
| 319 | 330 | 
| 320   CompileRun( | 331   CompileRun( | 
| 321       "delete o.foo;" | 332       "delete o.foo;" | 
| 322       "f(o)"); | 333       "f(o)"); | 
| 323   CHECK_EQ(POLYMORPHIC, nexus.StateFromFeedback()); | 334   CHECK_EQ(POLYMORPHIC, nexus.StateFromFeedback()); | 
| (...skipping 24 matching lines...) Expand all  Loading... | 
| 348 | 359 | 
| 349   // Function f has 3 LoadICs, one for each o, but the ICs share the same | 360   // Function f has 3 LoadICs, one for each o, but the ICs share the same | 
| 350   // feedback vector IC slot. | 361   // feedback vector IC slot. | 
| 351   CompileRun( | 362   CompileRun( | 
| 352       "o = 10;" | 363       "o = 10;" | 
| 353       "function f() {" | 364       "function f() {" | 
| 354       "  var x = o + 10;" | 365       "  var x = o + 10;" | 
| 355       "  return o + x + o;" | 366       "  return o + x + o;" | 
| 356       "}" | 367       "}" | 
| 357       "f();"); | 368       "f();"); | 
| 358   Handle<JSFunction> f = Handle<JSFunction>::cast(v8::Utils::OpenHandle( | 369   Handle<JSFunction> f = GetFunction("f"); | 
| 359       *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f"))))); |  | 
| 360   // There should be one IC slot. | 370   // There should be one IC slot. | 
| 361   Handle<TypeFeedbackVector> feedback_vector = | 371   Handle<TypeFeedbackVector> feedback_vector = | 
| 362       Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate); | 372       Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate); | 
| 363   FeedbackVectorHelper helper(feedback_vector); | 373   FeedbackVectorHelper helper(feedback_vector); | 
| 364   CHECK_EQ(1, helper.slot_count()); | 374   CHECK_EQ(1, helper.slot_count()); | 
| 365   FeedbackVectorSlot slot(0); | 375   FeedbackVectorSlot slot(0); | 
| 366   LoadICNexus nexus(feedback_vector, slot); | 376   LoadICNexus nexus(feedback_vector, slot); | 
| 367   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); | 377   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); | 
| 368 } | 378 } | 
| 369 | 379 | 
| 370 | 380 | 
| 371 TEST(VectorLoadICOnSmi) { | 381 TEST(VectorLoadICOnSmi) { | 
| 372   if (i::FLAG_always_opt) return; | 382   if (i::FLAG_always_opt) return; | 
| 373   CcTest::InitializeVM(); | 383   CcTest::InitializeVM(); | 
| 374   LocalContext context; | 384   LocalContext context; | 
| 375   v8::HandleScope scope(context->GetIsolate()); | 385   v8::HandleScope scope(context->GetIsolate()); | 
| 376   Isolate* isolate = CcTest::i_isolate(); | 386   Isolate* isolate = CcTest::i_isolate(); | 
| 377   Heap* heap = isolate->heap(); | 387   Heap* heap = isolate->heap(); | 
| 378 | 388 | 
| 379   // Make sure function f has a call that uses a type feedback slot. | 389   // Make sure function f has a call that uses a type feedback slot. | 
| 380   CompileRun( | 390   CompileRun( | 
| 381       "var o = { foo: 3 };" | 391       "var o = { foo: 3 };" | 
| 382       "function f(a) { return a.foo; } f(o);"); | 392       "function f(a) { return a.foo; } f(o);"); | 
| 383   Handle<JSFunction> f = Handle<JSFunction>::cast(v8::Utils::OpenHandle( | 393   Handle<JSFunction> f = GetFunction("f"); | 
| 384       *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f"))))); |  | 
| 385   // There should be one IC. | 394   // There should be one IC. | 
| 386   Handle<TypeFeedbackVector> feedback_vector = | 395   Handle<TypeFeedbackVector> feedback_vector = | 
| 387       Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate); | 396       Handle<TypeFeedbackVector>(f->shared()->feedback_vector(), isolate); | 
| 388   FeedbackVectorSlot slot(0); | 397   FeedbackVectorSlot slot(0); | 
| 389   LoadICNexus nexus(feedback_vector, slot); | 398   LoadICNexus nexus(feedback_vector, slot); | 
| 390   CHECK_EQ(PREMONOMORPHIC, nexus.StateFromFeedback()); | 399   CHECK_EQ(PREMONOMORPHIC, nexus.StateFromFeedback()); | 
| 391 | 400 | 
| 392   CompileRun("f(34)"); | 401   CompileRun("f(34)"); | 
| 393   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); | 402   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); | 
| 394   // Verify that the monomorphic map is the one we expect. | 403   // Verify that the monomorphic map is the one we expect. | 
| 395   Map* number_map = heap->heap_number_map(); | 404   Map* number_map = heap->heap_number_map(); | 
| 396   CHECK_EQ(number_map, nexus.FindFirstMap()); | 405   CHECK_EQ(number_map, nexus.FindFirstMap()); | 
| 397 | 406 | 
| 398   // Now go polymorphic on o. | 407   // Now go polymorphic on o. | 
| 399   CompileRun("f(o)"); | 408   CompileRun("f(o)"); | 
| 400   CHECK_EQ(POLYMORPHIC, nexus.StateFromFeedback()); | 409   CHECK_EQ(POLYMORPHIC, nexus.StateFromFeedback()); | 
| 401 | 410 | 
| 402   MapHandleList maps; | 411   MapHandleList maps; | 
| 403   nexus.FindAllMaps(&maps); | 412   nexus.FindAllMaps(&maps); | 
| 404   CHECK_EQ(2, maps.length()); | 413   CHECK_EQ(2, maps.length()); | 
| 405 | 414 | 
| 406   // One of the maps should be the o map. | 415   // One of the maps should be the o map. | 
| 407   Handle<JSObject> o = v8::Utils::OpenHandle( | 416   v8::MaybeLocal<v8::Value> v8_o = | 
| 408       *v8::Handle<v8::Object>::Cast(CcTest::global()->Get(v8_str("o")))); | 417       CcTest::global()->Get(context.local(), v8_str("o")); | 
|  | 418   Handle<JSObject> o = | 
|  | 419       Handle<JSObject>::cast(v8::Utils::OpenHandle(*v8_o.ToLocalChecked())); | 
| 409   bool number_map_found = false; | 420   bool number_map_found = false; | 
| 410   bool o_map_found = false; | 421   bool o_map_found = false; | 
| 411   for (int i = 0; i < maps.length(); i++) { | 422   for (int i = 0; i < maps.length(); i++) { | 
| 412     Handle<Map> current = maps[i]; | 423     Handle<Map> current = maps[i]; | 
| 413     if (*current == number_map) | 424     if (*current == number_map) | 
| 414       number_map_found = true; | 425       number_map_found = true; | 
| 415     else if (*current == o->map()) | 426     else if (*current == o->map()) | 
| 416       o_map_found = true; | 427       o_map_found = true; | 
| 417   } | 428   } | 
| 418   CHECK(number_map_found && o_map_found); | 429   CHECK(number_map_found && o_map_found); | 
| 419 | 430 | 
| 420   // The degree of polymorphism doesn't change. | 431   // The degree of polymorphism doesn't change. | 
| 421   CompileRun("f(100)"); | 432   CompileRun("f(100)"); | 
| 422   CHECK_EQ(POLYMORPHIC, nexus.StateFromFeedback()); | 433   CHECK_EQ(POLYMORPHIC, nexus.StateFromFeedback()); | 
| 423   MapHandleList maps2; | 434   MapHandleList maps2; | 
| 424   nexus.FindAllMaps(&maps2); | 435   nexus.FindAllMaps(&maps2); | 
| 425   CHECK_EQ(2, maps2.length()); | 436   CHECK_EQ(2, maps2.length()); | 
| 426 } | 437 } | 
| 427 | 438 | 
| 428 | 439 | 
| 429 static Handle<JSFunction> GetFunction(const char* name) { |  | 
| 430   Handle<JSFunction> f = Handle<JSFunction>::cast(v8::Utils::OpenHandle( |  | 
| 431       *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str(name))))); |  | 
| 432   return f; |  | 
| 433 } |  | 
| 434 |  | 
| 435 |  | 
| 436 TEST(ReferenceContextAllocatesNoSlots) { | 440 TEST(ReferenceContextAllocatesNoSlots) { | 
| 437   if (i::FLAG_always_opt) return; | 441   if (i::FLAG_always_opt) return; | 
| 438   CcTest::InitializeVM(); | 442   CcTest::InitializeVM(); | 
| 439   LocalContext context; | 443   LocalContext context; | 
| 440   v8::HandleScope scope(context->GetIsolate()); | 444   v8::HandleScope scope(context->GetIsolate()); | 
| 441   Isolate* isolate = CcTest::i_isolate(); | 445   Isolate* isolate = CcTest::i_isolate(); | 
| 442 | 446 | 
| 443   { | 447   { | 
| 444     CompileRun( | 448     CompileRun( | 
| 445         "function testvar(x) {" | 449         "function testvar(x) {" | 
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 595   // There should be one IC slot. | 599   // There should be one IC slot. | 
| 596   Handle<TypeFeedbackVector> feedback_vector(f->shared()->feedback_vector()); | 600   Handle<TypeFeedbackVector> feedback_vector(f->shared()->feedback_vector()); | 
| 597   FeedbackVectorHelper helper(feedback_vector); | 601   FeedbackVectorHelper helper(feedback_vector); | 
| 598   CHECK_EQ(1, helper.slot_count()); | 602   CHECK_EQ(1, helper.slot_count()); | 
| 599   FeedbackVectorSlot slot(0); | 603   FeedbackVectorSlot slot(0); | 
| 600   StoreICNexus nexus(feedback_vector, slot); | 604   StoreICNexus nexus(feedback_vector, slot); | 
| 601   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); | 605   CHECK_EQ(MONOMORPHIC, nexus.StateFromFeedback()); | 
| 602 } | 606 } | 
| 603 | 607 | 
| 604 }  // namespace | 608 }  // namespace | 
| OLD | NEW | 
|---|