OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 miss_label, | 146 miss_label, |
147 &done, | 147 &done, |
148 properties, | 148 properties, |
149 name, | 149 name, |
150 r1); | 150 r1); |
151 __ bind(&done); | 151 __ bind(&done); |
152 __ DecrementCounter(counters->negative_lookups_miss(), 1); | 152 __ DecrementCounter(counters->negative_lookups_miss(), 1); |
153 } | 153 } |
154 | 154 |
155 | 155 |
156 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
157 // handlified. | |
158 static MaybeObject* TryGenerateDictionaryNegativeLookup(MacroAssembler* masm, | |
159 Label* miss_label, | |
160 Register receiver, | |
161 String* name, | |
162 Register r0, | |
163 Register r1) { | |
164 ASSERT(name->IsSymbol()); | |
165 Counters* counters = masm->isolate()->counters(); | |
166 __ IncrementCounter(counters->negative_lookups(), 1); | |
167 __ IncrementCounter(counters->negative_lookups_miss(), 1); | |
168 | |
169 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); | |
170 | |
171 const int kInterceptorOrAccessCheckNeededMask = | |
172 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | |
173 | |
174 // Bail out if the receiver has a named interceptor or requires access checks. | |
175 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), | |
176 kInterceptorOrAccessCheckNeededMask); | |
177 __ j(not_zero, miss_label); | |
178 | |
179 // Check that receiver is a JSObject. | |
180 __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE); | |
181 __ j(below, miss_label); | |
182 | |
183 // Load properties array. | |
184 Register properties = r0; | |
185 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); | |
186 | |
187 // Check that the properties array is a dictionary. | |
188 __ cmp(FieldOperand(properties, HeapObject::kMapOffset), | |
189 Immediate(masm->isolate()->factory()->hash_table_map())); | |
190 __ j(not_equal, miss_label); | |
191 | |
192 Label done; | |
193 MaybeObject* result = | |
194 StringDictionaryLookupStub::TryGenerateNegativeLookup(masm, | |
195 miss_label, | |
196 &done, | |
197 properties, | |
198 name, | |
199 r1); | |
200 if (result->IsFailure()) return result; | |
201 | |
202 __ bind(&done); | |
203 __ DecrementCounter(counters->negative_lookups_miss(), 1); | |
204 | |
205 return result; | |
206 } | |
207 | |
208 | |
209 void StubCache::GenerateProbe(MacroAssembler* masm, | 156 void StubCache::GenerateProbe(MacroAssembler* masm, |
210 Code::Flags flags, | 157 Code::Flags flags, |
211 Register receiver, | 158 Register receiver, |
212 Register name, | 159 Register name, |
213 Register scratch, | 160 Register scratch, |
214 Register extra, | 161 Register extra, |
215 Register extra2) { | 162 Register extra2) { |
216 Label miss; | 163 Label miss; |
217 | 164 |
218 // Assert that code is valid. The shifting code relies on the entry size | 165 // Assert that code is valid. The shifting code relies on the entry size |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 int index, | 214 int index, |
268 Register prototype) { | 215 Register prototype) { |
269 __ LoadGlobalFunction(index, prototype); | 216 __ LoadGlobalFunction(index, prototype); |
270 __ LoadGlobalFunctionInitialMap(prototype, prototype); | 217 __ LoadGlobalFunctionInitialMap(prototype, prototype); |
271 // Load the prototype from the initial map. | 218 // Load the prototype from the initial map. |
272 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); | 219 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); |
273 } | 220 } |
274 | 221 |
275 | 222 |
276 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( | 223 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( |
277 MacroAssembler* masm, int index, Register prototype, Label* miss) { | 224 MacroAssembler* masm, |
| 225 int index, |
| 226 Register prototype, |
| 227 Label* miss) { |
278 // Check we're still in the same context. | 228 // Check we're still in the same context. |
279 __ cmp(Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)), | 229 __ cmp(Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)), |
280 masm->isolate()->global()); | 230 masm->isolate()->global()); |
281 __ j(not_equal, miss); | 231 __ j(not_equal, miss); |
282 // Get the global function with the given index. | 232 // Get the global function with the given index. |
283 JSFunction* function = | 233 Handle<JSFunction> function( |
284 JSFunction::cast(masm->isolate()->global_context()->get(index)); | 234 JSFunction::cast(masm->isolate()->global_context()->get(index))); |
285 // Load its initial map. The global functions all have initial maps. | 235 // Load its initial map. The global functions all have initial maps. |
286 __ Set(prototype, Immediate(Handle<Map>(function->initial_map()))); | 236 __ Set(prototype, Immediate(Handle<Map>(function->initial_map()))); |
287 // Load the prototype from the initial map. | 237 // Load the prototype from the initial map. |
288 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); | 238 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); |
289 } | 239 } |
290 | 240 |
291 | 241 |
292 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, | 242 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, |
293 Register receiver, | 243 Register receiver, |
294 Register scratch, | 244 Register scratch, |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
389 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); | 339 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); |
390 __ mov(dst, FieldOperand(dst, offset)); | 340 __ mov(dst, FieldOperand(dst, offset)); |
391 } | 341 } |
392 } | 342 } |
393 | 343 |
394 | 344 |
395 static void PushInterceptorArguments(MacroAssembler* masm, | 345 static void PushInterceptorArguments(MacroAssembler* masm, |
396 Register receiver, | 346 Register receiver, |
397 Register holder, | 347 Register holder, |
398 Register name, | 348 Register name, |
399 JSObject* holder_obj) { | 349 Handle<JSObject> holder_obj) { |
400 __ push(name); | 350 __ push(name); |
401 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); | 351 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); |
402 ASSERT(!masm->isolate()->heap()->InNewSpace(interceptor)); | 352 ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); |
403 Register scratch = name; | 353 Register scratch = name; |
404 __ mov(scratch, Immediate(Handle<Object>(interceptor))); | 354 __ mov(scratch, Immediate(interceptor)); |
405 __ push(scratch); | 355 __ push(scratch); |
406 __ push(receiver); | 356 __ push(receiver); |
407 __ push(holder); | 357 __ push(holder); |
408 __ push(FieldOperand(scratch, InterceptorInfo::kDataOffset)); | 358 __ push(FieldOperand(scratch, InterceptorInfo::kDataOffset)); |
409 } | 359 } |
410 | 360 |
411 | 361 |
412 static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, | 362 static void CompileCallLoadPropertyWithInterceptor( |
413 Register receiver, | 363 MacroAssembler* masm, |
414 Register holder, | 364 Register receiver, |
415 Register name, | 365 Register holder, |
416 JSObject* holder_obj) { | 366 Register name, |
| 367 Handle<JSObject> holder_obj) { |
417 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 368 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
418 __ CallExternalReference( | 369 __ CallExternalReference( |
419 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), | 370 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), |
420 masm->isolate()), | 371 masm->isolate()), |
421 5); | 372 5); |
422 } | 373 } |
423 | 374 |
424 | 375 |
425 // Number of pointers to be reserved on stack for fast API call. | 376 // Number of pointers to be reserved on stack for fast API call. |
426 static const int kFastApiCallArguments = 3; | 377 static const int kFastApiCallArguments = 3; |
(...skipping 26 matching lines...) Expand all Loading... |
453 // -- esp[kFastApiCallArguments * 4 + 4] : last argument in the internal | 404 // -- esp[kFastApiCallArguments * 4 + 4] : last argument in the internal |
454 // frame. | 405 // frame. |
455 // ----------------------------------- | 406 // ----------------------------------- |
456 __ pop(scratch); | 407 __ pop(scratch); |
457 __ add(esp, Immediate(kPointerSize * kFastApiCallArguments)); | 408 __ add(esp, Immediate(kPointerSize * kFastApiCallArguments)); |
458 __ push(scratch); | 409 __ push(scratch); |
459 } | 410 } |
460 | 411 |
461 | 412 |
462 // Generates call to API function. | 413 // Generates call to API function. |
463 static MaybeObject* GenerateFastApiCall(MacroAssembler* masm, | 414 static void GenerateFastApiCall(MacroAssembler* masm, |
464 const CallOptimization& optimization, | 415 const CallOptimization& optimization, |
465 int argc) { | 416 int argc) { |
466 // ----------- S t a t e ------------- | 417 // ----------- S t a t e ------------- |
467 // -- esp[0] : return address | 418 // -- esp[0] : return address |
468 // -- esp[4] : object passing the type check | 419 // -- esp[4] : object passing the type check |
469 // (last fast api call extra argument, | 420 // (last fast api call extra argument, |
470 // set by CheckPrototypes) | 421 // set by CheckPrototypes) |
471 // -- esp[8] : api function | 422 // -- esp[8] : api function |
472 // (first fast api call extra argument) | 423 // (first fast api call extra argument) |
473 // -- esp[12] : api call data | 424 // -- esp[12] : api call data |
474 // -- esp[16] : last argument | 425 // -- esp[16] : last argument |
475 // -- ... | 426 // -- ... |
476 // -- esp[(argc + 3) * 4] : first argument | 427 // -- esp[(argc + 3) * 4] : first argument |
477 // -- esp[(argc + 4) * 4] : receiver | 428 // -- esp[(argc + 4) * 4] : receiver |
478 // ----------------------------------- | 429 // ----------------------------------- |
479 // Get the function and setup the context. | 430 // Get the function and setup the context. |
480 JSFunction* function = optimization.constant_function(); | 431 Handle<JSFunction> function = optimization.constant_function(); |
481 __ mov(edi, Immediate(Handle<JSFunction>(function))); | 432 __ mov(edi, Immediate(function)); |
482 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 433 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
483 | 434 |
484 // Pass the additional arguments. | 435 // Pass the additional arguments. |
485 __ mov(Operand(esp, 2 * kPointerSize), edi); | 436 __ mov(Operand(esp, 2 * kPointerSize), edi); |
486 Object* call_data = optimization.api_call_info()->data(); | 437 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); |
487 Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info()); | 438 Handle<Object> call_data(api_call_info->data()); |
488 if (masm->isolate()->heap()->InNewSpace(call_data)) { | 439 if (masm->isolate()->heap()->InNewSpace(*call_data)) { |
489 __ mov(ecx, api_call_info_handle); | 440 __ mov(ecx, api_call_info); |
490 __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset)); | 441 __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset)); |
491 __ mov(Operand(esp, 3 * kPointerSize), ebx); | 442 __ mov(Operand(esp, 3 * kPointerSize), ebx); |
492 } else { | 443 } else { |
493 __ mov(Operand(esp, 3 * kPointerSize), | 444 __ mov(Operand(esp, 3 * kPointerSize), Immediate(call_data)); |
494 Immediate(Handle<Object>(call_data))); | |
495 } | 445 } |
496 | 446 |
497 // Prepare arguments. | 447 // Prepare arguments. |
498 __ lea(eax, Operand(esp, 3 * kPointerSize)); | 448 __ lea(eax, Operand(esp, 3 * kPointerSize)); |
499 | 449 |
500 Object* callback = optimization.api_call_info()->callback(); | |
501 Address api_function_address = v8::ToCData<Address>(callback); | |
502 ApiFunction fun(api_function_address); | |
503 | |
504 const int kApiArgc = 1; // API function gets reference to the v8::Arguments. | 450 const int kApiArgc = 1; // API function gets reference to the v8::Arguments. |
505 | 451 |
506 // Allocate the v8::Arguments structure in the arguments' space since | 452 // Allocate the v8::Arguments structure in the arguments' space since |
507 // it's not controlled by GC. | 453 // it's not controlled by GC. |
508 const int kApiStackSpace = 4; | 454 const int kApiStackSpace = 4; |
509 | 455 |
510 __ PrepareCallApiFunction(kApiArgc + kApiStackSpace); | 456 __ PrepareCallApiFunction(kApiArgc + kApiStackSpace); |
511 | 457 |
512 __ mov(ApiParameterOperand(1), eax); // v8::Arguments::implicit_args_. | 458 __ mov(ApiParameterOperand(1), eax); // v8::Arguments::implicit_args_. |
513 __ add(eax, Immediate(argc * kPointerSize)); | 459 __ add(eax, Immediate(argc * kPointerSize)); |
514 __ mov(ApiParameterOperand(2), eax); // v8::Arguments::values_. | 460 __ mov(ApiParameterOperand(2), eax); // v8::Arguments::values_. |
515 __ Set(ApiParameterOperand(3), Immediate(argc)); // v8::Arguments::length_. | 461 __ Set(ApiParameterOperand(3), Immediate(argc)); // v8::Arguments::length_. |
516 // v8::Arguments::is_construct_call_. | 462 // v8::Arguments::is_construct_call_. |
517 __ Set(ApiParameterOperand(4), Immediate(0)); | 463 __ Set(ApiParameterOperand(4), Immediate(0)); |
518 | 464 |
519 // v8::InvocationCallback's argument. | 465 // v8::InvocationCallback's argument. |
520 __ lea(eax, ApiParameterOperand(1)); | 466 __ lea(eax, ApiParameterOperand(1)); |
521 __ mov(ApiParameterOperand(0), eax); | 467 __ mov(ApiParameterOperand(0), eax); |
522 | 468 |
523 // Emitting a stub call may try to allocate (if the code is not | 469 // Function address is a foreign pointer outside V8's heap. |
524 // already generated). Do not allow the assembler to perform a | 470 Address function_address = v8::ToCData<Address>(api_call_info->callback()); |
525 // garbage collection but instead return the allocation failure | 471 __ CallApiFunctionAndReturn(function_address, |
526 // object. | 472 argc + kFastApiCallArguments + 1); |
527 return masm->TryCallApiFunctionAndReturn(&fun, | |
528 argc + kFastApiCallArguments + 1); | |
529 } | 473 } |
530 | 474 |
531 | 475 |
532 class CallInterceptorCompiler BASE_EMBEDDED { | 476 class CallInterceptorCompiler BASE_EMBEDDED { |
533 public: | 477 public: |
534 CallInterceptorCompiler(StubCompiler* stub_compiler, | 478 CallInterceptorCompiler(StubCompiler* stub_compiler, |
535 const ParameterCount& arguments, | 479 const ParameterCount& arguments, |
536 Register name, | 480 Register name, |
537 Code::ExtraICState extra_state) | 481 Code::ExtraICState extra_state) |
538 : stub_compiler_(stub_compiler), | 482 : stub_compiler_(stub_compiler), |
539 arguments_(arguments), | 483 arguments_(arguments), |
540 name_(name), | 484 name_(name), |
541 extra_state_(extra_state) {} | 485 extra_state_(extra_state) {} |
542 | 486 |
543 MaybeObject* Compile(MacroAssembler* masm, | 487 void Compile(MacroAssembler* masm, |
544 JSObject* object, | 488 Handle<JSObject> object, |
545 JSObject* holder, | 489 Handle<JSObject> holder, |
546 String* name, | 490 Handle<String> name, |
547 LookupResult* lookup, | 491 LookupResult* lookup, |
548 Register receiver, | 492 Register receiver, |
549 Register scratch1, | 493 Register scratch1, |
550 Register scratch2, | 494 Register scratch2, |
551 Register scratch3, | 495 Register scratch3, |
552 Label* miss) { | 496 Label* miss) { |
553 ASSERT(holder->HasNamedInterceptor()); | 497 ASSERT(holder->HasNamedInterceptor()); |
554 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 498 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
555 | 499 |
556 // Check that the receiver isn't a smi. | 500 // Check that the receiver isn't a smi. |
557 __ JumpIfSmi(receiver, miss); | 501 __ JumpIfSmi(receiver, miss); |
558 | 502 |
559 CallOptimization optimization(lookup); | 503 CallOptimization optimization(lookup); |
560 | |
561 if (optimization.is_constant_call()) { | 504 if (optimization.is_constant_call()) { |
562 return CompileCacheable(masm, | 505 CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3, |
563 object, | 506 holder, lookup, name, optimization, miss); |
564 receiver, | |
565 scratch1, | |
566 scratch2, | |
567 scratch3, | |
568 holder, | |
569 lookup, | |
570 name, | |
571 optimization, | |
572 miss); | |
573 } else { | 507 } else { |
574 CompileRegular(masm, | 508 CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3, |
575 object, | 509 name, holder, miss); |
576 receiver, | |
577 scratch1, | |
578 scratch2, | |
579 scratch3, | |
580 name, | |
581 holder, | |
582 miss); | |
583 return masm->isolate()->heap()->undefined_value(); // Success. | |
584 } | 510 } |
585 } | 511 } |
586 | 512 |
587 private: | 513 private: |
588 MaybeObject* CompileCacheable(MacroAssembler* masm, | 514 void CompileCacheable(MacroAssembler* masm, |
589 JSObject* object, | 515 Handle<JSObject> object, |
590 Register receiver, | 516 Register receiver, |
591 Register scratch1, | 517 Register scratch1, |
592 Register scratch2, | 518 Register scratch2, |
593 Register scratch3, | 519 Register scratch3, |
594 JSObject* interceptor_holder, | 520 Handle<JSObject> interceptor_holder, |
595 LookupResult* lookup, | 521 LookupResult* lookup, |
596 String* name, | 522 Handle<String> name, |
597 const CallOptimization& optimization, | 523 const CallOptimization& optimization, |
598 Label* miss_label) { | 524 Label* miss_label) { |
599 ASSERT(optimization.is_constant_call()); | 525 ASSERT(optimization.is_constant_call()); |
600 ASSERT(!lookup->holder()->IsGlobalObject()); | 526 ASSERT(!lookup->holder()->IsGlobalObject()); |
601 | 527 |
602 int depth1 = kInvalidProtoDepth; | 528 int depth1 = kInvalidProtoDepth; |
603 int depth2 = kInvalidProtoDepth; | 529 int depth2 = kInvalidProtoDepth; |
604 bool can_do_fast_api_call = false; | 530 bool can_do_fast_api_call = false; |
605 if (optimization.is_simple_api_call() && | 531 if (optimization.is_simple_api_call() && |
606 !lookup->holder()->IsGlobalObject()) { | 532 !lookup->holder()->IsGlobalObject()) { |
607 depth1 = | 533 depth1 = optimization.GetPrototypeDepthOfExpectedType( |
608 optimization.GetPrototypeDepthOfExpectedType(object, | 534 object, interceptor_holder); |
609 interceptor_holder); | |
610 if (depth1 == kInvalidProtoDepth) { | 535 if (depth1 == kInvalidProtoDepth) { |
611 depth2 = | 536 depth2 = optimization.GetPrototypeDepthOfExpectedType( |
612 optimization.GetPrototypeDepthOfExpectedType(interceptor_holder, | 537 interceptor_holder, Handle<JSObject>(lookup->holder())); |
613 lookup->holder()); | |
614 } | 538 } |
615 can_do_fast_api_call = (depth1 != kInvalidProtoDepth) || | 539 can_do_fast_api_call = |
616 (depth2 != kInvalidProtoDepth); | 540 depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth; |
617 } | 541 } |
618 | 542 |
619 Counters* counters = masm->isolate()->counters(); | 543 Counters* counters = masm->isolate()->counters(); |
620 __ IncrementCounter(counters->call_const_interceptor(), 1); | 544 __ IncrementCounter(counters->call_const_interceptor(), 1); |
621 | 545 |
622 if (can_do_fast_api_call) { | 546 if (can_do_fast_api_call) { |
623 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1); | 547 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1); |
624 ReserveSpaceForFastApiCall(masm, scratch1); | 548 ReserveSpaceForFastApiCall(masm, scratch1); |
625 } | 549 } |
626 | 550 |
627 // Check that the maps from receiver to interceptor's holder | 551 // Check that the maps from receiver to interceptor's holder |
628 // haven't changed and thus we can invoke interceptor. | 552 // haven't changed and thus we can invoke interceptor. |
629 Label miss_cleanup; | 553 Label miss_cleanup; |
630 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; | 554 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; |
631 Register holder = | 555 Register holder = |
632 stub_compiler_->CheckPrototypes(object, receiver, | 556 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, |
633 interceptor_holder, scratch1, | 557 scratch1, scratch2, scratch3, |
634 scratch2, scratch3, name, depth1, miss); | 558 name, depth1, miss); |
635 | 559 |
636 // Invoke an interceptor and if it provides a value, | 560 // Invoke an interceptor and if it provides a value, |
637 // branch to |regular_invoke|. | 561 // branch to |regular_invoke|. |
638 Label regular_invoke; | 562 Label regular_invoke; |
639 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, | 563 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, |
640 ®ular_invoke); | 564 ®ular_invoke); |
641 | 565 |
642 // Interceptor returned nothing for this property. Try to use cached | 566 // Interceptor returned nothing for this property. Try to use cached |
643 // constant function. | 567 // constant function. |
644 | 568 |
645 // Check that the maps from interceptor's holder to constant function's | 569 // Check that the maps from interceptor's holder to constant function's |
646 // holder haven't changed and thus we can use cached constant function. | 570 // holder haven't changed and thus we can use cached constant function. |
647 if (interceptor_holder != lookup->holder()) { | 571 if (*interceptor_holder != lookup->holder()) { |
648 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, | 572 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, |
649 lookup->holder(), scratch1, | 573 Handle<JSObject>(lookup->holder()), |
650 scratch2, scratch3, name, depth2, miss); | 574 scratch1, scratch2, scratch3, |
| 575 name, depth2, miss); |
651 } else { | 576 } else { |
652 // CheckPrototypes has a side effect of fetching a 'holder' | 577 // CheckPrototypes has a side effect of fetching a 'holder' |
653 // for API (object which is instanceof for the signature). It's | 578 // for API (object which is instanceof for the signature). It's |
654 // safe to omit it here, as if present, it should be fetched | 579 // safe to omit it here, as if present, it should be fetched |
655 // by the previous CheckPrototypes. | 580 // by the previous CheckPrototypes. |
656 ASSERT(depth2 == kInvalidProtoDepth); | 581 ASSERT(depth2 == kInvalidProtoDepth); |
657 } | 582 } |
658 | 583 |
659 // Invoke function. | 584 // Invoke function. |
660 if (can_do_fast_api_call) { | 585 if (can_do_fast_api_call) { |
661 MaybeObject* result = | 586 GenerateFastApiCall(masm, optimization, arguments_.immediate()); |
662 GenerateFastApiCall(masm, optimization, arguments_.immediate()); | |
663 if (result->IsFailure()) return result; | |
664 } else { | 587 } else { |
665 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 588 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
666 ? CALL_AS_FUNCTION | 589 ? CALL_AS_FUNCTION |
667 : CALL_AS_METHOD; | 590 : CALL_AS_METHOD; |
668 __ InvokeFunction(optimization.constant_function(), arguments_, | 591 __ InvokeFunction(optimization.constant_function(), arguments_, |
669 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 592 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
670 } | 593 } |
671 | 594 |
672 // Deferred code for fast API call case---clean preallocated space. | 595 // Deferred code for fast API call case---clean preallocated space. |
673 if (can_do_fast_api_call) { | 596 if (can_do_fast_api_call) { |
674 __ bind(&miss_cleanup); | 597 __ bind(&miss_cleanup); |
675 FreeSpaceForFastApiCall(masm, scratch1); | 598 FreeSpaceForFastApiCall(masm, scratch1); |
676 __ jmp(miss_label); | 599 __ jmp(miss_label); |
677 } | 600 } |
678 | 601 |
679 // Invoke a regular function. | 602 // Invoke a regular function. |
680 __ bind(®ular_invoke); | 603 __ bind(®ular_invoke); |
681 if (can_do_fast_api_call) { | 604 if (can_do_fast_api_call) { |
682 FreeSpaceForFastApiCall(masm, scratch1); | 605 FreeSpaceForFastApiCall(masm, scratch1); |
683 } | 606 } |
684 | |
685 return masm->isolate()->heap()->undefined_value(); // Success. | |
686 } | 607 } |
687 | 608 |
688 void CompileRegular(MacroAssembler* masm, | 609 void CompileRegular(MacroAssembler* masm, |
689 JSObject* object, | 610 Handle<JSObject> object, |
690 Register receiver, | 611 Register receiver, |
691 Register scratch1, | 612 Register scratch1, |
692 Register scratch2, | 613 Register scratch2, |
693 Register scratch3, | 614 Register scratch3, |
694 String* name, | 615 Handle<String> name, |
695 JSObject* interceptor_holder, | 616 Handle<JSObject> interceptor_holder, |
696 Label* miss_label) { | 617 Label* miss_label) { |
697 Register holder = | 618 Register holder = |
698 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, | 619 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, |
699 scratch1, scratch2, scratch3, name, | 620 scratch1, scratch2, scratch3, |
700 miss_label); | 621 name, miss_label); |
701 | 622 |
702 FrameScope scope(masm, StackFrame::INTERNAL); | 623 FrameScope scope(masm, StackFrame::INTERNAL); |
703 // Save the name_ register across the call. | 624 // Save the name_ register across the call. |
704 __ push(name_); | 625 __ push(name_); |
705 | 626 |
706 PushInterceptorArguments(masm, | 627 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); |
707 receiver, | |
708 holder, | |
709 name_, | |
710 interceptor_holder); | |
711 | 628 |
712 __ CallExternalReference( | 629 __ CallExternalReference( |
713 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), | 630 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), |
714 masm->isolate()), | 631 masm->isolate()), |
715 5); | 632 5); |
716 | 633 |
717 // Restore the name_ register. | 634 // Restore the name_ register. |
718 __ pop(name_); | 635 __ pop(name_); |
719 | 636 |
720 // Leave the internal frame. | 637 // Leave the internal frame. |
721 } | 638 } |
722 | 639 |
723 void LoadWithInterceptor(MacroAssembler* masm, | 640 void LoadWithInterceptor(MacroAssembler* masm, |
724 Register receiver, | 641 Register receiver, |
725 Register holder, | 642 Register holder, |
726 JSObject* holder_obj, | 643 Handle<JSObject> holder_obj, |
727 Label* interceptor_succeeded) { | 644 Label* interceptor_succeeded) { |
728 { | 645 { |
729 FrameScope scope(masm, StackFrame::INTERNAL); | 646 FrameScope scope(masm, StackFrame::INTERNAL); |
730 __ push(holder); // Save the holder. | 647 __ push(holder); // Save the holder. |
731 __ push(name_); // Save the name. | 648 __ push(name_); // Save the name. |
732 | 649 |
733 CompileCallLoadPropertyWithInterceptor(masm, | 650 CompileCallLoadPropertyWithInterceptor(masm, |
734 receiver, | 651 receiver, |
735 holder, | 652 holder, |
736 name_, | 653 name_, |
(...skipping 18 matching lines...) Expand all Loading... |
755 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { | 672 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { |
756 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); | 673 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); |
757 Handle<Code> code = (kind == Code::LOAD_IC) | 674 Handle<Code> code = (kind == Code::LOAD_IC) |
758 ? masm->isolate()->builtins()->LoadIC_Miss() | 675 ? masm->isolate()->builtins()->LoadIC_Miss() |
759 : masm->isolate()->builtins()->KeyedLoadIC_Miss(); | 676 : masm->isolate()->builtins()->KeyedLoadIC_Miss(); |
760 __ jmp(code, RelocInfo::CODE_TARGET); | 677 __ jmp(code, RelocInfo::CODE_TARGET); |
761 } | 678 } |
762 | 679 |
763 | 680 |
764 void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) { | 681 void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) { |
765 Code* code = masm->isolate()->builtins()->builtin( | 682 Handle<Code> code = |
766 Builtins::kKeyedLoadIC_MissForceGeneric); | 683 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); |
767 Handle<Code> ic(code); | 684 __ jmp(code, RelocInfo::CODE_TARGET); |
768 __ jmp(ic, RelocInfo::CODE_TARGET); | |
769 } | 685 } |
770 | 686 |
771 | 687 |
772 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 688 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
773 // but may be destroyed if store is successful. | 689 // but may be destroyed if store is successful. |
774 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 690 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
775 Handle<JSObject> object, | 691 Handle<JSObject> object, |
776 int index, | 692 int index, |
777 Handle<Map> transition, | 693 Handle<Map> transition, |
778 Register receiver_reg, | 694 Register receiver_reg, |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
876 __ mov(scratch, Immediate(cell)); | 792 __ mov(scratch, Immediate(cell)); |
877 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), | 793 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), |
878 Immediate(the_hole)); | 794 Immediate(the_hole)); |
879 } else { | 795 } else { |
880 __ cmp(Operand::Cell(cell), Immediate(the_hole)); | 796 __ cmp(Operand::Cell(cell), Immediate(the_hole)); |
881 } | 797 } |
882 __ j(not_equal, miss); | 798 __ j(not_equal, miss); |
883 } | 799 } |
884 | 800 |
885 | 801 |
886 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
887 // handlified. | |
888 MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCell( | |
889 MacroAssembler* masm, | |
890 GlobalObject* global, | |
891 String* name, | |
892 Register scratch, | |
893 Label* miss) { | |
894 Object* probe; | |
895 { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); | |
896 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | |
897 } | |
898 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); | |
899 ASSERT(cell->value()->IsTheHole()); | |
900 if (Serializer::enabled()) { | |
901 __ mov(scratch, Immediate(Handle<Object>(cell))); | |
902 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), | |
903 Immediate(masm->isolate()->factory()->the_hole_value())); | |
904 } else { | |
905 __ cmp(Operand::Cell(Handle<JSGlobalPropertyCell>(cell)), | |
906 Immediate(masm->isolate()->factory()->the_hole_value())); | |
907 } | |
908 __ j(not_equal, miss); | |
909 return cell; | |
910 } | |
911 | |
912 | |
913 // Calls GenerateCheckPropertyCell for each global object in the prototype chain | 802 // Calls GenerateCheckPropertyCell for each global object in the prototype chain |
914 // from object to (but not including) holder. | 803 // from object to (but not including) holder. |
915 static void GenerateCheckPropertyCells(MacroAssembler* masm, | 804 static void GenerateCheckPropertyCells(MacroAssembler* masm, |
916 Handle<JSObject> object, | 805 Handle<JSObject> object, |
917 Handle<JSObject> holder, | 806 Handle<JSObject> holder, |
918 Handle<String> name, | 807 Handle<String> name, |
919 Register scratch, | 808 Register scratch, |
920 Label* miss) { | 809 Label* miss) { |
921 Handle<JSObject> current = object; | 810 Handle<JSObject> current = object; |
922 while (!current.is_identical_to(holder)) { | 811 while (!current.is_identical_to(holder)) { |
923 if (current->IsGlobalObject()) { | 812 if (current->IsGlobalObject()) { |
924 GenerateCheckPropertyCell(masm, | 813 GenerateCheckPropertyCell(masm, |
925 Handle<GlobalObject>::cast(current), | 814 Handle<GlobalObject>::cast(current), |
926 name, | 815 name, |
927 scratch, | 816 scratch, |
928 miss); | 817 miss); |
929 } | 818 } |
930 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); | 819 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); |
931 } | 820 } |
932 } | 821 } |
933 | 822 |
934 | |
935 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
936 // handlified. | |
937 MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCells( | |
938 MacroAssembler* masm, | |
939 JSObject* object, | |
940 JSObject* holder, | |
941 String* name, | |
942 Register scratch, | |
943 Label* miss) { | |
944 JSObject* current = object; | |
945 while (current != holder) { | |
946 if (current->IsGlobalObject()) { | |
947 // Returns a cell or a failure. | |
948 MaybeObject* result = TryGenerateCheckPropertyCell( | |
949 masm, | |
950 GlobalObject::cast(current), | |
951 name, | |
952 scratch, | |
953 miss); | |
954 if (result->IsFailure()) return result; | |
955 } | |
956 ASSERT(current->IsJSObject()); | |
957 current = JSObject::cast(current->GetPrototype()); | |
958 } | |
959 return NULL; | |
960 } | |
961 | |
962 | |
963 #undef __ | 823 #undef __ |
964 #define __ ACCESS_MASM(masm()) | 824 #define __ ACCESS_MASM(masm()) |
965 | 825 |
966 | 826 |
967 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, | 827 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
968 Register object_reg, | 828 Register object_reg, |
969 Handle<JSObject> holder, | 829 Handle<JSObject> holder, |
970 Register holder_reg, | 830 Register holder_reg, |
971 Register scratch1, | 831 Register scratch1, |
972 Register scratch2, | 832 Register scratch2, |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1069 // If we've skipped any global objects, it's not enough to verify that | 929 // If we've skipped any global objects, it's not enough to verify that |
1070 // their maps haven't changed. We also need to check that the property | 930 // their maps haven't changed. We also need to check that the property |
1071 // cell for the property is still empty. | 931 // cell for the property is still empty. |
1072 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | 932 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
1073 | 933 |
1074 // Return the register containing the holder. | 934 // Return the register containing the holder. |
1075 return reg; | 935 return reg; |
1076 } | 936 } |
1077 | 937 |
1078 | 938 |
1079 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
1080 // handlified. | |
1081 Register StubCompiler::CheckPrototypes(JSObject* object, | |
1082 Register object_reg, | |
1083 JSObject* holder, | |
1084 Register holder_reg, | |
1085 Register scratch1, | |
1086 Register scratch2, | |
1087 String* name, | |
1088 int save_at_depth, | |
1089 Label* miss) { | |
1090 // Make sure there's no overlap between holder and object registers. | |
1091 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | |
1092 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | |
1093 && !scratch2.is(scratch1)); | |
1094 | |
1095 // Keep track of the current object in register reg. | |
1096 Register reg = object_reg; | |
1097 JSObject* current = object; | |
1098 int depth = 0; | |
1099 | |
1100 if (save_at_depth == depth) { | |
1101 __ mov(Operand(esp, kPointerSize), reg); | |
1102 } | |
1103 | |
1104 // Traverse the prototype chain and check the maps in the prototype chain for | |
1105 // fast and global objects or do negative lookup for normal objects. | |
1106 while (current != holder) { | |
1107 depth++; | |
1108 | |
1109 // Only global objects and objects that do not require access | |
1110 // checks are allowed in stubs. | |
1111 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | |
1112 | |
1113 ASSERT(current->GetPrototype()->IsJSObject()); | |
1114 JSObject* prototype = JSObject::cast(current->GetPrototype()); | |
1115 if (!current->HasFastProperties() && | |
1116 !current->IsJSGlobalObject() && | |
1117 !current->IsJSGlobalProxy()) { | |
1118 if (!name->IsSymbol()) { | |
1119 MaybeObject* maybe_lookup_result = heap()->LookupSymbol(name); | |
1120 Object* lookup_result = NULL; // Initialization to please compiler. | |
1121 if (!maybe_lookup_result->ToObject(&lookup_result)) { | |
1122 set_failure(Failure::cast(maybe_lookup_result)); | |
1123 return reg; | |
1124 } | |
1125 name = String::cast(lookup_result); | |
1126 } | |
1127 ASSERT(current->property_dictionary()->FindEntry(name) == | |
1128 StringDictionary::kNotFound); | |
1129 | |
1130 MaybeObject* negative_lookup = | |
1131 TryGenerateDictionaryNegativeLookup(masm(), miss, reg, name, | |
1132 scratch1, scratch2); | |
1133 if (negative_lookup->IsFailure()) { | |
1134 set_failure(Failure::cast(negative_lookup)); | |
1135 return reg; | |
1136 } | |
1137 | |
1138 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | |
1139 reg = holder_reg; // from now the object is in holder_reg | |
1140 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | |
1141 } else if (heap()->InNewSpace(prototype)) { | |
1142 // Get the map of the current object. | |
1143 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | |
1144 __ cmp(scratch1, Immediate(Handle<Map>(current->map()))); | |
1145 // Branch on the result of the map check. | |
1146 __ j(not_equal, miss); | |
1147 // Check access rights to the global object. This has to happen | |
1148 // after the map check so that we know that the object is | |
1149 // actually a global object. | |
1150 if (current->IsJSGlobalProxy()) { | |
1151 __ CheckAccessGlobalProxy(reg, scratch1, miss); | |
1152 | |
1153 // Restore scratch register to be the map of the object. | |
1154 // We load the prototype from the map in the scratch register. | |
1155 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | |
1156 } | |
1157 // The prototype is in new space; we cannot store a reference | |
1158 // to it in the code. Load it from the map. | |
1159 reg = holder_reg; // from now the object is in holder_reg | |
1160 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | |
1161 } else { | |
1162 // Check the map of the current object. | |
1163 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | |
1164 Immediate(Handle<Map>(current->map()))); | |
1165 // Branch on the result of the map check. | |
1166 __ j(not_equal, miss); | |
1167 // Check access rights to the global object. This has to happen | |
1168 // after the map check so that we know that the object is | |
1169 // actually a global object. | |
1170 if (current->IsJSGlobalProxy()) { | |
1171 __ CheckAccessGlobalProxy(reg, scratch1, miss); | |
1172 } | |
1173 // The prototype is in old space; load it directly. | |
1174 reg = holder_reg; // from now the object is in holder_reg | |
1175 __ mov(reg, Handle<JSObject>(prototype)); | |
1176 } | |
1177 | |
1178 if (save_at_depth == depth) { | |
1179 __ mov(Operand(esp, kPointerSize), reg); | |
1180 } | |
1181 | |
1182 // Go to the next object in the prototype chain. | |
1183 current = prototype; | |
1184 } | |
1185 ASSERT(current == holder); | |
1186 | |
1187 // Log the check depth. | |
1188 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | |
1189 | |
1190 // Check the holder map. | |
1191 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | |
1192 Immediate(Handle<Map>(holder->map()))); | |
1193 __ j(not_equal, miss); | |
1194 | |
1195 // Perform security check for access to the global object. | |
1196 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | |
1197 if (holder->IsJSGlobalProxy()) { | |
1198 __ CheckAccessGlobalProxy(reg, scratch1, miss); | |
1199 } | |
1200 | |
1201 // If we've skipped any global objects, it's not enough to verify | |
1202 // that their maps haven't changed. We also need to check that the | |
1203 // property cell for the property is still empty. | |
1204 MaybeObject* result = TryGenerateCheckPropertyCells(masm(), | |
1205 object, | |
1206 holder, | |
1207 name, | |
1208 scratch1, | |
1209 miss); | |
1210 if (result->IsFailure()) set_failure(Failure::cast(result)); | |
1211 | |
1212 // Return the register containing the holder. | |
1213 return reg; | |
1214 } | |
1215 | |
1216 | |
1217 void StubCompiler::GenerateLoadField(Handle<JSObject> object, | 939 void StubCompiler::GenerateLoadField(Handle<JSObject> object, |
1218 Handle<JSObject> holder, | 940 Handle<JSObject> holder, |
1219 Register receiver, | 941 Register receiver, |
1220 Register scratch1, | 942 Register scratch1, |
1221 Register scratch2, | 943 Register scratch2, |
1222 Register scratch3, | 944 Register scratch3, |
1223 int index, | 945 int index, |
1224 Handle<String> name, | 946 Handle<String> name, |
1225 Label* miss) { | 947 Label* miss) { |
1226 // Check that the receiver isn't a smi. | 948 // Check that the receiver isn't a smi. |
1227 __ JumpIfSmi(receiver, miss); | 949 __ JumpIfSmi(receiver, miss); |
1228 | 950 |
1229 // Check the prototype chain. | 951 // Check the prototype chain. |
1230 Register reg = CheckPrototypes( | 952 Register reg = CheckPrototypes( |
1231 object, receiver, holder, scratch1, scratch2, scratch3, name, miss); | 953 object, receiver, holder, scratch1, scratch2, scratch3, name, miss); |
1232 | 954 |
1233 // Get the value from the properties. | 955 // Get the value from the properties. |
1234 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); | 956 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); |
1235 __ ret(0); | 957 __ ret(0); |
1236 } | 958 } |
1237 | 959 |
1238 | 960 |
1239 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, | 961 void StubCompiler::GenerateLoadCallback(Handle<JSObject> object, |
1240 JSObject* holder, | 962 Handle<JSObject> holder, |
1241 Register receiver, | 963 Register receiver, |
1242 Register name_reg, | 964 Register name_reg, |
1243 Register scratch1, | 965 Register scratch1, |
1244 Register scratch2, | 966 Register scratch2, |
1245 Register scratch3, | 967 Register scratch3, |
1246 AccessorInfo* callback, | 968 Handle<AccessorInfo> callback, |
1247 String* name, | 969 Handle<String> name, |
1248 Label* miss) { | 970 Label* miss) { |
1249 // Check that the receiver isn't a smi. | 971 // Check that the receiver isn't a smi. |
1250 __ JumpIfSmi(receiver, miss); | 972 __ JumpIfSmi(receiver, miss); |
1251 | 973 |
1252 // Check that the maps haven't changed. | 974 // Check that the maps haven't changed. |
1253 Register reg = | 975 Register reg = CheckPrototypes(object, receiver, holder, scratch1, |
1254 CheckPrototypes(object, receiver, holder, scratch1, | 976 scratch2, scratch3, name, miss); |
1255 scratch2, scratch3, name, miss); | |
1256 | |
1257 Handle<AccessorInfo> callback_handle(callback); | |
1258 | 977 |
1259 // Insert additional parameters into the stack frame above return address. | 978 // Insert additional parameters into the stack frame above return address. |
1260 ASSERT(!scratch3.is(reg)); | 979 ASSERT(!scratch3.is(reg)); |
1261 __ pop(scratch3); // Get return address to place it below. | 980 __ pop(scratch3); // Get return address to place it below. |
1262 | 981 |
1263 __ push(receiver); // receiver | 982 __ push(receiver); // receiver |
1264 __ mov(scratch2, esp); | 983 __ mov(scratch2, esp); |
1265 ASSERT(!scratch2.is(reg)); | 984 ASSERT(!scratch2.is(reg)); |
1266 __ push(reg); // holder | 985 __ push(reg); // holder |
1267 // Push data from AccessorInfo. | 986 // Push data from AccessorInfo. |
1268 if (isolate()->heap()->InNewSpace(callback_handle->data())) { | 987 if (isolate()->heap()->InNewSpace(callback->data())) { |
1269 __ mov(scratch1, Immediate(callback_handle)); | 988 __ mov(scratch1, Immediate(callback)); |
1270 __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); | 989 __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); |
1271 } else { | 990 } else { |
1272 __ push(Immediate(Handle<Object>(callback_handle->data()))); | 991 __ push(Immediate(Handle<Object>(callback->data()))); |
1273 } | 992 } |
1274 | 993 |
1275 // Save a pointer to where we pushed the arguments pointer. | 994 // Save a pointer to where we pushed the arguments pointer. |
1276 // This will be passed as the const AccessorInfo& to the C++ callback. | 995 // This will be passed as the const AccessorInfo& to the C++ callback. |
1277 __ push(scratch2); | 996 __ push(scratch2); |
1278 | 997 |
1279 __ push(name_reg); // name | 998 __ push(name_reg); // name |
1280 __ mov(ebx, esp); // esp points to reference to name (handler). | 999 __ mov(ebx, esp); // esp points to reference to name (handler). |
1281 | 1000 |
1282 __ push(scratch3); // Restore return address. | 1001 __ push(scratch3); // Restore return address. |
1283 | 1002 |
1284 // Do call through the api. | |
1285 Address getter_address = v8::ToCData<Address>(callback->getter()); | |
1286 ApiFunction fun(getter_address); | |
1287 | |
1288 // 3 elements array for v8::Agruments::values_, handler for name and pointer | 1003 // 3 elements array for v8::Agruments::values_, handler for name and pointer |
1289 // to the values (it considered as smi in GC). | 1004 // to the values (it considered as smi in GC). |
1290 const int kStackSpace = 5; | 1005 const int kStackSpace = 5; |
1291 const int kApiArgc = 2; | 1006 const int kApiArgc = 2; |
1292 | 1007 |
1293 __ PrepareCallApiFunction(kApiArgc); | 1008 __ PrepareCallApiFunction(kApiArgc); |
1294 __ mov(ApiParameterOperand(0), ebx); // name. | 1009 __ mov(ApiParameterOperand(0), ebx); // name. |
1295 __ add(ebx, Immediate(kPointerSize)); | 1010 __ add(ebx, Immediate(kPointerSize)); |
1296 __ mov(ApiParameterOperand(1), ebx); // arguments pointer. | 1011 __ mov(ApiParameterOperand(1), ebx); // arguments pointer. |
1297 | 1012 |
1298 // Emitting a stub call may try to allocate (if the code is not | 1013 // Emitting a stub call may try to allocate (if the code is not |
1299 // already generated). Do not allow the assembler to perform a | 1014 // already generated). Do not allow the assembler to perform a |
1300 // garbage collection but instead return the allocation failure | 1015 // garbage collection but instead return the allocation failure |
1301 // object. | 1016 // object. |
1302 return masm()->TryCallApiFunctionAndReturn(&fun, kStackSpace); | 1017 Address getter_address = v8::ToCData<Address>(callback->getter()); |
| 1018 __ CallApiFunctionAndReturn(getter_address, kStackSpace); |
1303 } | 1019 } |
1304 | 1020 |
1305 | 1021 |
1306 void StubCompiler::GenerateLoadConstant(Handle<JSObject> object, | 1022 void StubCompiler::GenerateLoadConstant(Handle<JSObject> object, |
1307 Handle<JSObject> holder, | 1023 Handle<JSObject> holder, |
1308 Register receiver, | 1024 Register receiver, |
1309 Register scratch1, | 1025 Register scratch1, |
1310 Register scratch2, | 1026 Register scratch2, |
1311 Register scratch3, | 1027 Register scratch3, |
1312 Handle<Object> value, | 1028 Handle<Object> value, |
1313 Handle<String> name, | 1029 Handle<String> name, |
1314 Label* miss) { | 1030 Label* miss) { |
1315 // Check that the receiver isn't a smi. | 1031 // Check that the receiver isn't a smi. |
1316 __ JumpIfSmi(receiver, miss); | 1032 __ JumpIfSmi(receiver, miss); |
1317 | 1033 |
1318 // Check that the maps haven't changed. | 1034 // Check that the maps haven't changed. |
1319 CheckPrototypes( | 1035 CheckPrototypes( |
1320 object, receiver, holder, scratch1, scratch2, scratch3, name, miss); | 1036 object, receiver, holder, scratch1, scratch2, scratch3, name, miss); |
1321 | 1037 |
1322 // Return the constant value. | 1038 // Return the constant value. |
1323 __ mov(eax, value); | 1039 __ mov(eax, value); |
1324 __ ret(0); | 1040 __ ret(0); |
1325 } | 1041 } |
1326 | 1042 |
1327 | 1043 |
1328 void StubCompiler::GenerateLoadInterceptor(JSObject* object, | 1044 void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, |
1329 JSObject* interceptor_holder, | 1045 Handle<JSObject> interceptor_holder, |
1330 LookupResult* lookup, | 1046 LookupResult* lookup, |
1331 Register receiver, | 1047 Register receiver, |
1332 Register name_reg, | 1048 Register name_reg, |
1333 Register scratch1, | 1049 Register scratch1, |
1334 Register scratch2, | 1050 Register scratch2, |
1335 Register scratch3, | 1051 Register scratch3, |
1336 String* name, | 1052 Handle<String> name, |
1337 Label* miss) { | 1053 Label* miss) { |
1338 ASSERT(interceptor_holder->HasNamedInterceptor()); | 1054 ASSERT(interceptor_holder->HasNamedInterceptor()); |
1339 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 1055 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
1340 | 1056 |
1341 // Check that the receiver isn't a smi. | 1057 // Check that the receiver isn't a smi. |
1342 __ JumpIfSmi(receiver, miss); | 1058 __ JumpIfSmi(receiver, miss); |
1343 | 1059 |
1344 // So far the most popular follow ups for interceptor loads are FIELD | 1060 // So far the most popular follow ups for interceptor loads are FIELD |
1345 // and CALLBACKS, so inline only them, other cases may be added | 1061 // and CALLBACKS, so inline only them, other cases may be added |
1346 // later. | 1062 // later. |
1347 bool compile_followup_inline = false; | 1063 bool compile_followup_inline = false; |
1348 if (lookup->IsProperty() && lookup->IsCacheable()) { | 1064 if (lookup->IsProperty() && lookup->IsCacheable()) { |
1349 if (lookup->type() == FIELD) { | 1065 if (lookup->type() == FIELD) { |
1350 compile_followup_inline = true; | 1066 compile_followup_inline = true; |
1351 } else if (lookup->type() == CALLBACKS && | 1067 } else if (lookup->type() == CALLBACKS && |
1352 lookup->GetCallbackObject()->IsAccessorInfo() && | 1068 lookup->GetCallbackObject()->IsAccessorInfo()) { |
1353 AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL) { | 1069 compile_followup_inline = |
1354 compile_followup_inline = true; | 1070 AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL; |
1355 } | 1071 } |
1356 } | 1072 } |
1357 | 1073 |
1358 if (compile_followup_inline) { | 1074 if (compile_followup_inline) { |
1359 // Compile the interceptor call, followed by inline code to load the | 1075 // Compile the interceptor call, followed by inline code to load the |
1360 // property from further up the prototype chain if the call fails. | 1076 // property from further up the prototype chain if the call fails. |
1361 // Check that the maps haven't changed. | 1077 // Check that the maps haven't changed. |
1362 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, | 1078 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, |
1363 scratch1, scratch2, scratch3, | 1079 scratch1, scratch2, scratch3, |
1364 name, miss); | 1080 name, miss); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1398 __ pop(holder_reg); | 1114 __ pop(holder_reg); |
1399 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { | 1115 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { |
1400 __ pop(receiver); | 1116 __ pop(receiver); |
1401 } | 1117 } |
1402 | 1118 |
1403 // Leave the internal frame. | 1119 // Leave the internal frame. |
1404 } | 1120 } |
1405 | 1121 |
1406 // Check that the maps from interceptor's holder to lookup's holder | 1122 // Check that the maps from interceptor's holder to lookup's holder |
1407 // haven't changed. And load lookup's holder into holder_reg. | 1123 // haven't changed. And load lookup's holder into holder_reg. |
1408 if (interceptor_holder != lookup->holder()) { | 1124 if (*interceptor_holder != lookup->holder()) { |
1409 holder_reg = CheckPrototypes(interceptor_holder, | 1125 holder_reg = CheckPrototypes(interceptor_holder, |
1410 holder_reg, | 1126 holder_reg, |
1411 lookup->holder(), | 1127 Handle<JSObject>(lookup->holder()), |
1412 scratch1, | 1128 scratch1, |
1413 scratch2, | 1129 scratch2, |
1414 scratch3, | 1130 scratch3, |
1415 name, | 1131 name, |
1416 miss); | 1132 miss); |
1417 } | 1133 } |
1418 | 1134 |
1419 if (lookup->type() == FIELD) { | 1135 if (lookup->type() == FIELD) { |
1420 // We found FIELD property in prototype chain of interceptor's holder. | 1136 // We found FIELD property in prototype chain of interceptor's holder. |
1421 // Retrieve a field from field's holder. | 1137 // Retrieve a field from field's holder. |
1422 GenerateFastPropertyLoad(masm(), eax, holder_reg, | 1138 GenerateFastPropertyLoad(masm(), eax, holder_reg, |
1423 Handle<JSObject>(lookup->holder()), | 1139 Handle<JSObject>(lookup->holder()), |
1424 lookup->GetFieldIndex()); | 1140 lookup->GetFieldIndex()); |
1425 __ ret(0); | 1141 __ ret(0); |
1426 } else { | 1142 } else { |
1427 // We found CALLBACKS property in prototype chain of interceptor's | 1143 // We found CALLBACKS property in prototype chain of interceptor's |
1428 // holder. | 1144 // holder. |
1429 ASSERT(lookup->type() == CALLBACKS); | 1145 ASSERT(lookup->type() == CALLBACKS); |
1430 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); | 1146 Handle<AccessorInfo> callback( |
1431 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); | 1147 AccessorInfo::cast(lookup->GetCallbackObject())); |
1432 ASSERT(callback != NULL); | |
1433 ASSERT(callback->getter() != NULL); | 1148 ASSERT(callback->getter() != NULL); |
1434 | 1149 |
1435 // Tail call to runtime. | 1150 // Tail call to runtime. |
1436 // Important invariant in CALLBACKS case: the code above must be | 1151 // Important invariant in CALLBACKS case: the code above must be |
1437 // structured to never clobber |receiver| register. | 1152 // structured to never clobber |receiver| register. |
1438 __ pop(scratch2); // return address | 1153 __ pop(scratch2); // return address |
1439 __ push(receiver); | 1154 __ push(receiver); |
1440 __ push(holder_reg); | 1155 __ push(holder_reg); |
1441 __ mov(holder_reg, Immediate(Handle<AccessorInfo>(callback))); | 1156 __ mov(holder_reg, Immediate(callback)); |
1442 __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset)); | 1157 __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset)); |
1443 __ push(holder_reg); | 1158 __ push(holder_reg); |
1444 __ push(name_reg); | 1159 __ push(name_reg); |
1445 __ push(scratch2); // restore return address | 1160 __ push(scratch2); // restore return address |
1446 | 1161 |
1447 ExternalReference ref = | 1162 ExternalReference ref = |
1448 ExternalReference(IC_Utility(IC::kLoadCallbackProperty), | 1163 ExternalReference(IC_Utility(IC::kLoadCallbackProperty), |
1449 masm()->isolate()); | 1164 masm()->isolate()); |
1450 __ TailCallExternalReference(ref, 5, 1); | 1165 __ TailCallExternalReference(ref, 5, 1); |
1451 } | 1166 } |
(...skipping 17 matching lines...) Expand all Loading... |
1469 | 1184 |
1470 | 1185 |
1471 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { | 1186 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { |
1472 if (kind_ == Code::KEYED_CALL_IC) { | 1187 if (kind_ == Code::KEYED_CALL_IC) { |
1473 __ cmp(ecx, Immediate(name)); | 1188 __ cmp(ecx, Immediate(name)); |
1474 __ j(not_equal, miss); | 1189 __ j(not_equal, miss); |
1475 } | 1190 } |
1476 } | 1191 } |
1477 | 1192 |
1478 | 1193 |
1479 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, | 1194 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, |
1480 JSObject* holder, | 1195 Handle<JSObject> holder, |
1481 String* name, | 1196 Handle<String> name, |
1482 Label* miss) { | 1197 Label* miss) { |
1483 ASSERT(holder->IsGlobalObject()); | 1198 ASSERT(holder->IsGlobalObject()); |
1484 | 1199 |
1485 // Get the number of arguments. | 1200 // Get the number of arguments. |
1486 const int argc = arguments().immediate(); | 1201 const int argc = arguments().immediate(); |
1487 | 1202 |
1488 // Get the receiver from the stack. | 1203 // Get the receiver from the stack. |
1489 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1204 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1490 | 1205 |
1491 // If the object is the holder then we know that it's a global | 1206 // If the object is the holder then we know that it's a global |
1492 // object which can only happen for contextual calls. In this case, | 1207 // object which can only happen for contextual calls. In this case, |
1493 // the receiver cannot be a smi. | 1208 // the receiver cannot be a smi. |
1494 if (object != holder) { | 1209 if (!object.is_identical_to(holder)) { |
1495 __ JumpIfSmi(edx, miss); | 1210 __ JumpIfSmi(edx, miss); |
1496 } | 1211 } |
1497 | 1212 |
1498 // Check that the maps haven't changed. | 1213 // Check that the maps haven't changed. |
1499 CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss); | 1214 CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss); |
1500 } | 1215 } |
1501 | 1216 |
1502 | 1217 |
1503 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, | 1218 void CallStubCompiler::GenerateLoadFunctionFromCell( |
1504 JSFunction* function, | 1219 Handle<JSGlobalPropertyCell> cell, |
1505 Label* miss) { | 1220 Handle<JSFunction> function, |
| 1221 Label* miss) { |
1506 // Get the value from the cell. | 1222 // Get the value from the cell. |
1507 if (Serializer::enabled()) { | 1223 if (Serializer::enabled()) { |
1508 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 1224 __ mov(edi, Immediate(cell)); |
1509 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); | 1225 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); |
1510 } else { | 1226 } else { |
1511 __ mov(edi, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); | 1227 __ mov(edi, Operand::Cell(cell)); |
1512 } | 1228 } |
1513 | 1229 |
1514 // Check that the cell contains the same function. | 1230 // Check that the cell contains the same function. |
1515 if (isolate()->heap()->InNewSpace(function)) { | 1231 if (isolate()->heap()->InNewSpace(*function)) { |
1516 // We can't embed a pointer to a function in new space so we have | 1232 // We can't embed a pointer to a function in new space so we have |
1517 // to verify that the shared function info is unchanged. This has | 1233 // to verify that the shared function info is unchanged. This has |
1518 // the nice side effect that multiple closures based on the same | 1234 // the nice side effect that multiple closures based on the same |
1519 // function can all use this call IC. Before we load through the | 1235 // function can all use this call IC. Before we load through the |
1520 // function, we have to verify that it still is a function. | 1236 // function, we have to verify that it still is a function. |
1521 __ JumpIfSmi(edi, miss); | 1237 __ JumpIfSmi(edi, miss); |
1522 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | 1238 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); |
1523 __ j(not_equal, miss); | 1239 __ j(not_equal, miss); |
1524 | 1240 |
1525 // Check the shared function info. Make sure it hasn't changed. | 1241 // Check the shared function info. Make sure it hasn't changed. |
1526 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), | 1242 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), |
1527 Immediate(Handle<SharedFunctionInfo>(function->shared()))); | 1243 Immediate(Handle<SharedFunctionInfo>(function->shared()))); |
1528 __ j(not_equal, miss); | |
1529 } else { | 1244 } else { |
1530 __ cmp(edi, Immediate(Handle<JSFunction>(function))); | 1245 __ cmp(edi, Immediate(function)); |
1531 __ j(not_equal, miss); | |
1532 } | 1246 } |
| 1247 __ j(not_equal, miss); |
1533 } | 1248 } |
1534 | 1249 |
1535 | 1250 |
1536 void CallStubCompiler::GenerateMissBranch() { | 1251 void CallStubCompiler::GenerateMissBranch() { |
1537 Handle<Code> code = | 1252 Handle<Code> code = |
1538 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), | 1253 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
1539 kind_, | 1254 kind_, |
1540 extra_state_); | 1255 extra_state_); |
1541 __ jmp(code, RelocInfo::CODE_TARGET); | 1256 __ jmp(code, RelocInfo::CODE_TARGET); |
1542 } | 1257 } |
1543 | 1258 |
1544 | 1259 |
1545 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
1546 // handlified. | |
1547 MaybeObject* CallStubCompiler::TryGenerateMissBranch() { | |
1548 MaybeObject* maybe_obj = | |
1549 isolate()->stub_cache()->TryComputeCallMiss(arguments().immediate(), | |
1550 kind_, | |
1551 extra_state_); | |
1552 Object* obj; | |
1553 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
1554 __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); | |
1555 return obj; | |
1556 } | |
1557 | |
1558 | |
1559 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, | 1260 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
1560 Handle<JSObject> holder, | 1261 Handle<JSObject> holder, |
1561 int index, | 1262 int index, |
1562 Handle<String> name) { | 1263 Handle<String> name) { |
1563 // ----------- S t a t e ------------- | 1264 // ----------- S t a t e ------------- |
1564 // -- ecx : name | 1265 // -- ecx : name |
1565 // -- esp[0] : return address | 1266 // -- esp[0] : return address |
1566 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1267 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1567 // -- ... | 1268 // -- ... |
1568 // -- esp[(argc + 1) * 4] : receiver | 1269 // -- esp[(argc + 1) * 4] : receiver |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1605 | 1306 |
1606 // Handle call cache miss. | 1307 // Handle call cache miss. |
1607 __ bind(&miss); | 1308 __ bind(&miss); |
1608 GenerateMissBranch(); | 1309 GenerateMissBranch(); |
1609 | 1310 |
1610 // Return the generated code. | 1311 // Return the generated code. |
1611 return GetCode(FIELD, name); | 1312 return GetCode(FIELD, name); |
1612 } | 1313 } |
1613 | 1314 |
1614 | 1315 |
1615 MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, | 1316 Handle<Code> CallStubCompiler::CompileArrayPushCall( |
1616 JSObject* holder, | 1317 Handle<Object> object, |
1617 JSGlobalPropertyCell* cell, | 1318 Handle<JSObject> holder, |
1618 JSFunction* function, | 1319 Handle<JSGlobalPropertyCell> cell, |
1619 String* name) { | 1320 Handle<JSFunction> function, |
| 1321 Handle<String> name) { |
1620 // ----------- S t a t e ------------- | 1322 // ----------- S t a t e ------------- |
1621 // -- ecx : name | 1323 // -- ecx : name |
1622 // -- esp[0] : return address | 1324 // -- esp[0] : return address |
1623 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1325 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1624 // -- ... | 1326 // -- ... |
1625 // -- esp[(argc + 1) * 4] : receiver | 1327 // -- esp[(argc + 1) * 4] : receiver |
1626 // ----------------------------------- | 1328 // ----------------------------------- |
1627 | 1329 |
1628 // If object is not an array, bail out to regular call. | 1330 // If object is not an array, bail out to regular call. |
1629 if (!object->IsJSArray() || cell != NULL) { | 1331 if (!object->IsJSArray() || !cell.is_null()) { |
1630 return isolate()->heap()->undefined_value(); | 1332 return Handle<Code>::null(); |
1631 } | 1333 } |
1632 | 1334 |
1633 Label miss; | 1335 Label miss; |
1634 | 1336 |
1635 GenerateNameCheck(Handle<String>(name), &miss); | 1337 GenerateNameCheck(name, &miss); |
1636 | 1338 |
1637 // Get the receiver from the stack. | 1339 // Get the receiver from the stack. |
1638 const int argc = arguments().immediate(); | 1340 const int argc = arguments().immediate(); |
1639 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1341 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1640 | 1342 |
1641 // Check that the receiver isn't a smi. | 1343 // Check that the receiver isn't a smi. |
1642 __ JumpIfSmi(edx, &miss); | 1344 __ JumpIfSmi(edx, &miss); |
1643 | 1345 |
1644 CheckPrototypes(JSObject::cast(object), edx, | 1346 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, |
1645 holder, ebx, | 1347 name, &miss); |
1646 eax, edi, name, &miss); | |
1647 | 1348 |
1648 if (argc == 0) { | 1349 if (argc == 0) { |
1649 // Noop, return the length. | 1350 // Noop, return the length. |
1650 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); | 1351 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); |
1651 __ ret((argc + 1) * kPointerSize); | 1352 __ ret((argc + 1) * kPointerSize); |
1652 } else { | 1353 } else { |
1653 Label call_builtin; | 1354 Label call_builtin; |
1654 | 1355 |
1655 // Get the elements array of the object. | 1356 // Get the elements array of the object. |
1656 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); | 1357 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1698 | 1399 |
1699 // Save new length. | 1400 // Save new length. |
1700 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); | 1401 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); |
1701 | 1402 |
1702 // Push the element. | 1403 // Push the element. |
1703 __ lea(edx, FieldOperand(ebx, | 1404 __ lea(edx, FieldOperand(ebx, |
1704 eax, times_half_pointer_size, | 1405 eax, times_half_pointer_size, |
1705 FixedArray::kHeaderSize - argc * kPointerSize)); | 1406 FixedArray::kHeaderSize - argc * kPointerSize)); |
1706 __ mov(Operand(edx, 0), ecx); | 1407 __ mov(Operand(edx, 0), ecx); |
1707 | 1408 |
1708 __ RecordWrite( | 1409 __ RecordWrite(ebx, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, |
1709 ebx, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | 1410 OMIT_SMI_CHECK); |
1710 | 1411 |
1711 __ ret((argc + 1) * kPointerSize); | 1412 __ ret((argc + 1) * kPointerSize); |
1712 | 1413 |
1713 __ bind(&attempt_to_grow_elements); | 1414 __ bind(&attempt_to_grow_elements); |
1714 if (!FLAG_inline_new) { | 1415 if (!FLAG_inline_new) { |
1715 __ jmp(&call_builtin); | 1416 __ jmp(&call_builtin); |
1716 } | 1417 } |
1717 | 1418 |
1718 __ mov(edi, Operand(esp, argc * kPointerSize)); | 1419 __ mov(edi, Operand(esp, argc * kPointerSize)); |
1719 // Growing elements that are SMI-only requires special handling in case | 1420 // Growing elements that are SMI-only requires special handling in case |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1782 } | 1483 } |
1783 | 1484 |
1784 __ bind(&call_builtin); | 1485 __ bind(&call_builtin); |
1785 __ TailCallExternalReference( | 1486 __ TailCallExternalReference( |
1786 ExternalReference(Builtins::c_ArrayPush, isolate()), | 1487 ExternalReference(Builtins::c_ArrayPush, isolate()), |
1787 argc + 1, | 1488 argc + 1, |
1788 1); | 1489 1); |
1789 } | 1490 } |
1790 | 1491 |
1791 __ bind(&miss); | 1492 __ bind(&miss); |
1792 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1493 GenerateMissBranch(); |
1793 if (maybe_result->IsFailure()) return maybe_result; | |
1794 | 1494 |
1795 // Return the generated code. | 1495 // Return the generated code. |
1796 return TryGetCode(function); | 1496 return GetCode(function); |
1797 } | 1497 } |
1798 | 1498 |
1799 | 1499 |
1800 MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, | 1500 Handle<Code> CallStubCompiler::CompileArrayPopCall( |
1801 JSObject* holder, | 1501 Handle<Object> object, |
1802 JSGlobalPropertyCell* cell, | 1502 Handle<JSObject> holder, |
1803 JSFunction* function, | 1503 Handle<JSGlobalPropertyCell> cell, |
1804 String* name) { | 1504 Handle<JSFunction> function, |
| 1505 Handle<String> name) { |
1805 // ----------- S t a t e ------------- | 1506 // ----------- S t a t e ------------- |
1806 // -- ecx : name | 1507 // -- ecx : name |
1807 // -- esp[0] : return address | 1508 // -- esp[0] : return address |
1808 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1509 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1809 // -- ... | 1510 // -- ... |
1810 // -- esp[(argc + 1) * 4] : receiver | 1511 // -- esp[(argc + 1) * 4] : receiver |
1811 // ----------------------------------- | 1512 // ----------------------------------- |
1812 | 1513 |
1813 // If object is not an array, bail out to regular call. | 1514 // If object is not an array, bail out to regular call. |
1814 if (!object->IsJSArray() || cell != NULL) { | 1515 if (!object->IsJSArray() || !cell.is_null()) { |
1815 return heap()->undefined_value(); | 1516 return Handle<Code>::null(); |
1816 } | 1517 } |
1817 | 1518 |
1818 Label miss, return_undefined, call_builtin; | 1519 Label miss, return_undefined, call_builtin; |
1819 | 1520 |
1820 GenerateNameCheck(Handle<String>(name), &miss); | 1521 GenerateNameCheck(name, &miss); |
1821 | 1522 |
1822 // Get the receiver from the stack. | 1523 // Get the receiver from the stack. |
1823 const int argc = arguments().immediate(); | 1524 const int argc = arguments().immediate(); |
1824 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1525 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1825 | 1526 |
1826 // Check that the receiver isn't a smi. | 1527 // Check that the receiver isn't a smi. |
1827 __ JumpIfSmi(edx, &miss); | 1528 __ JumpIfSmi(edx, &miss); |
1828 CheckPrototypes(JSObject::cast(object), edx, | 1529 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, |
1829 holder, ebx, | 1530 name, &miss); |
1830 eax, edi, name, &miss); | |
1831 | 1531 |
1832 // Get the elements array of the object. | 1532 // Get the elements array of the object. |
1833 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); | 1533 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); |
1834 | 1534 |
1835 // Check that the elements are in fast mode and writable. | 1535 // Check that the elements are in fast mode and writable. |
1836 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), | 1536 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), |
1837 Immediate(factory()->fixed_array_map())); | 1537 Immediate(factory()->fixed_array_map())); |
1838 __ j(not_equal, &call_builtin); | 1538 __ j(not_equal, &call_builtin); |
1839 | 1539 |
1840 // Get the array's length into ecx and calculate new length. | 1540 // Get the array's length into ecx and calculate new length. |
(...skipping 24 matching lines...) Expand all Loading... |
1865 __ mov(eax, Immediate(factory()->undefined_value())); | 1565 __ mov(eax, Immediate(factory()->undefined_value())); |
1866 __ ret((argc + 1) * kPointerSize); | 1566 __ ret((argc + 1) * kPointerSize); |
1867 | 1567 |
1868 __ bind(&call_builtin); | 1568 __ bind(&call_builtin); |
1869 __ TailCallExternalReference( | 1569 __ TailCallExternalReference( |
1870 ExternalReference(Builtins::c_ArrayPop, isolate()), | 1570 ExternalReference(Builtins::c_ArrayPop, isolate()), |
1871 argc + 1, | 1571 argc + 1, |
1872 1); | 1572 1); |
1873 | 1573 |
1874 __ bind(&miss); | 1574 __ bind(&miss); |
1875 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1575 GenerateMissBranch(); |
1876 if (maybe_result->IsFailure()) return maybe_result; | |
1877 | 1576 |
1878 // Return the generated code. | 1577 // Return the generated code. |
1879 return TryGetCode(function); | 1578 return GetCode(function); |
1880 } | 1579 } |
1881 | 1580 |
1882 | 1581 |
1883 MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( | 1582 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( |
1884 Object* object, | 1583 Handle<Object> object, |
1885 JSObject* holder, | 1584 Handle<JSObject> holder, |
1886 JSGlobalPropertyCell* cell, | 1585 Handle<JSGlobalPropertyCell> cell, |
1887 JSFunction* function, | 1586 Handle<JSFunction> function, |
1888 String* name) { | 1587 Handle<String> name) { |
1889 // ----------- S t a t e ------------- | 1588 // ----------- S t a t e ------------- |
1890 // -- ecx : function name | 1589 // -- ecx : function name |
1891 // -- esp[0] : return address | 1590 // -- esp[0] : return address |
1892 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1591 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1893 // -- ... | 1592 // -- ... |
1894 // -- esp[(argc + 1) * 4] : receiver | 1593 // -- esp[(argc + 1) * 4] : receiver |
1895 // ----------------------------------- | 1594 // ----------------------------------- |
1896 | 1595 |
1897 // If object is not a string, bail out to regular call. | 1596 // If object is not a string, bail out to regular call. |
1898 if (!object->IsString() || cell != NULL) { | 1597 if (!object->IsString() || !cell.is_null()) { |
1899 return isolate()->heap()->undefined_value(); | 1598 return Handle<Code>::null(); |
1900 } | 1599 } |
1901 | 1600 |
1902 const int argc = arguments().immediate(); | 1601 const int argc = arguments().immediate(); |
1903 | 1602 |
1904 Label miss; | 1603 Label miss; |
1905 Label name_miss; | 1604 Label name_miss; |
1906 Label index_out_of_range; | 1605 Label index_out_of_range; |
1907 Label* index_out_of_range_label = &index_out_of_range; | 1606 Label* index_out_of_range_label = &index_out_of_range; |
1908 | 1607 |
1909 if (kind_ == Code::CALL_IC && | 1608 if (kind_ == Code::CALL_IC && |
1910 (CallICBase::StringStubState::decode(extra_state_) == | 1609 (CallICBase::StringStubState::decode(extra_state_) == |
1911 DEFAULT_STRING_STUB)) { | 1610 DEFAULT_STRING_STUB)) { |
1912 index_out_of_range_label = &miss; | 1611 index_out_of_range_label = &miss; |
1913 } | 1612 } |
1914 | 1613 |
1915 GenerateNameCheck(Handle<String>(name), &name_miss); | 1614 GenerateNameCheck(name, &name_miss); |
1916 | 1615 |
1917 // Check that the maps starting from the prototype haven't changed. | 1616 // Check that the maps starting from the prototype haven't changed. |
1918 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1617 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
1919 Context::STRING_FUNCTION_INDEX, | 1618 Context::STRING_FUNCTION_INDEX, |
1920 eax, | 1619 eax, |
1921 &miss); | 1620 &miss); |
1922 ASSERT(object != holder); | 1621 ASSERT(!object.is_identical_to(holder)); |
1923 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 1622 CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
1924 ebx, edx, edi, name, &miss); | 1623 eax, holder, ebx, edx, edi, name, &miss); |
1925 | 1624 |
1926 Register receiver = ebx; | 1625 Register receiver = ebx; |
1927 Register index = edi; | 1626 Register index = edi; |
1928 Register scratch = edx; | 1627 Register scratch = edx; |
1929 Register result = eax; | 1628 Register result = eax; |
1930 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); | 1629 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); |
1931 if (argc > 0) { | 1630 if (argc > 0) { |
1932 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); | 1631 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); |
1933 } else { | 1632 } else { |
1934 __ Set(index, Immediate(factory()->undefined_value())); | 1633 __ Set(index, Immediate(factory()->undefined_value())); |
1935 } | 1634 } |
1936 | 1635 |
1937 StringCharCodeAtGenerator char_code_at_generator(receiver, | 1636 StringCharCodeAtGenerator generator(receiver, |
1938 index, | 1637 index, |
1939 scratch, | 1638 scratch, |
1940 result, | 1639 result, |
1941 &miss, // When not a string. | 1640 &miss, // When not a string. |
1942 &miss, // When not a number. | 1641 &miss, // When not a number. |
1943 index_out_of_range_label, | 1642 index_out_of_range_label, |
1944 STRING_INDEX_IS_NUMBER); | 1643 STRING_INDEX_IS_NUMBER); |
1945 char_code_at_generator.GenerateFast(masm()); | 1644 generator.GenerateFast(masm()); |
1946 __ ret((argc + 1) * kPointerSize); | 1645 __ ret((argc + 1) * kPointerSize); |
1947 | 1646 |
1948 StubRuntimeCallHelper call_helper; | 1647 StubRuntimeCallHelper call_helper; |
1949 char_code_at_generator.GenerateSlow(masm(), call_helper); | 1648 generator.GenerateSlow(masm(), call_helper); |
1950 | 1649 |
1951 if (index_out_of_range.is_linked()) { | 1650 if (index_out_of_range.is_linked()) { |
1952 __ bind(&index_out_of_range); | 1651 __ bind(&index_out_of_range); |
1953 __ Set(eax, Immediate(factory()->nan_value())); | 1652 __ Set(eax, Immediate(factory()->nan_value())); |
1954 __ ret((argc + 1) * kPointerSize); | 1653 __ ret((argc + 1) * kPointerSize); |
1955 } | 1654 } |
1956 | 1655 |
1957 __ bind(&miss); | 1656 __ bind(&miss); |
1958 // Restore function name in ecx. | 1657 // Restore function name in ecx. |
1959 __ Set(ecx, Immediate(Handle<String>(name))); | 1658 __ Set(ecx, Immediate(name)); |
1960 __ bind(&name_miss); | 1659 __ bind(&name_miss); |
1961 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1660 GenerateMissBranch(); |
1962 if (maybe_result->IsFailure()) return maybe_result; | |
1963 | 1661 |
1964 // Return the generated code. | 1662 // Return the generated code. |
1965 return TryGetCode(function); | 1663 return GetCode(function); |
1966 } | 1664 } |
1967 | 1665 |
1968 | 1666 |
1969 MaybeObject* CallStubCompiler::CompileStringCharAtCall( | 1667 Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
1970 Object* object, | 1668 Handle<Object> object, |
1971 JSObject* holder, | 1669 Handle<JSObject> holder, |
1972 JSGlobalPropertyCell* cell, | 1670 Handle<JSGlobalPropertyCell> cell, |
1973 JSFunction* function, | 1671 Handle<JSFunction> function, |
1974 String* name) { | 1672 Handle<String> name) { |
1975 // ----------- S t a t e ------------- | 1673 // ----------- S t a t e ------------- |
1976 // -- ecx : function name | 1674 // -- ecx : function name |
1977 // -- esp[0] : return address | 1675 // -- esp[0] : return address |
1978 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1676 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1979 // -- ... | 1677 // -- ... |
1980 // -- esp[(argc + 1) * 4] : receiver | 1678 // -- esp[(argc + 1) * 4] : receiver |
1981 // ----------------------------------- | 1679 // ----------------------------------- |
1982 | 1680 |
1983 // If object is not a string, bail out to regular call. | 1681 // If object is not a string, bail out to regular call. |
1984 if (!object->IsString() || cell != NULL) { | 1682 if (!object->IsString() || !cell.is_null()) { |
1985 return heap()->undefined_value(); | 1683 return Handle<Code>::null(); |
1986 } | 1684 } |
1987 | 1685 |
1988 const int argc = arguments().immediate(); | 1686 const int argc = arguments().immediate(); |
1989 | 1687 |
1990 Label miss; | 1688 Label miss; |
1991 Label name_miss; | 1689 Label name_miss; |
1992 Label index_out_of_range; | 1690 Label index_out_of_range; |
1993 Label* index_out_of_range_label = &index_out_of_range; | 1691 Label* index_out_of_range_label = &index_out_of_range; |
1994 | 1692 |
1995 if (kind_ == Code::CALL_IC && | 1693 if (kind_ == Code::CALL_IC && |
1996 (CallICBase::StringStubState::decode(extra_state_) == | 1694 (CallICBase::StringStubState::decode(extra_state_) == |
1997 DEFAULT_STRING_STUB)) { | 1695 DEFAULT_STRING_STUB)) { |
1998 index_out_of_range_label = &miss; | 1696 index_out_of_range_label = &miss; |
1999 } | 1697 } |
2000 | 1698 |
2001 GenerateNameCheck(Handle<String>(name), &name_miss); | 1699 GenerateNameCheck(name, &name_miss); |
2002 | 1700 |
2003 // Check that the maps starting from the prototype haven't changed. | 1701 // Check that the maps starting from the prototype haven't changed. |
2004 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1702 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
2005 Context::STRING_FUNCTION_INDEX, | 1703 Context::STRING_FUNCTION_INDEX, |
2006 eax, | 1704 eax, |
2007 &miss); | 1705 &miss); |
2008 ASSERT(object != holder); | 1706 ASSERT(!object.is_identical_to(holder)); |
2009 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 1707 CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
2010 ebx, edx, edi, name, &miss); | 1708 eax, holder, ebx, edx, edi, name, &miss); |
2011 | 1709 |
2012 Register receiver = eax; | 1710 Register receiver = eax; |
2013 Register index = edi; | 1711 Register index = edi; |
2014 Register scratch1 = ebx; | 1712 Register scratch1 = ebx; |
2015 Register scratch2 = edx; | 1713 Register scratch2 = edx; |
2016 Register result = eax; | 1714 Register result = eax; |
2017 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); | 1715 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); |
2018 if (argc > 0) { | 1716 if (argc > 0) { |
2019 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); | 1717 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); |
2020 } else { | 1718 } else { |
2021 __ Set(index, Immediate(factory()->undefined_value())); | 1719 __ Set(index, Immediate(factory()->undefined_value())); |
2022 } | 1720 } |
2023 | 1721 |
2024 StringCharAtGenerator char_at_generator(receiver, | 1722 StringCharAtGenerator generator(receiver, |
2025 index, | 1723 index, |
2026 scratch1, | 1724 scratch1, |
2027 scratch2, | 1725 scratch2, |
2028 result, | 1726 result, |
2029 &miss, // When not a string. | 1727 &miss, // When not a string. |
2030 &miss, // When not a number. | 1728 &miss, // When not a number. |
2031 index_out_of_range_label, | 1729 index_out_of_range_label, |
2032 STRING_INDEX_IS_NUMBER); | 1730 STRING_INDEX_IS_NUMBER); |
2033 char_at_generator.GenerateFast(masm()); | 1731 generator.GenerateFast(masm()); |
2034 __ ret((argc + 1) * kPointerSize); | 1732 __ ret((argc + 1) * kPointerSize); |
2035 | 1733 |
2036 StubRuntimeCallHelper call_helper; | 1734 StubRuntimeCallHelper call_helper; |
2037 char_at_generator.GenerateSlow(masm(), call_helper); | 1735 generator.GenerateSlow(masm(), call_helper); |
2038 | 1736 |
2039 if (index_out_of_range.is_linked()) { | 1737 if (index_out_of_range.is_linked()) { |
2040 __ bind(&index_out_of_range); | 1738 __ bind(&index_out_of_range); |
2041 __ Set(eax, Immediate(factory()->empty_string())); | 1739 __ Set(eax, Immediate(factory()->empty_string())); |
2042 __ ret((argc + 1) * kPointerSize); | 1740 __ ret((argc + 1) * kPointerSize); |
2043 } | 1741 } |
2044 | 1742 |
2045 __ bind(&miss); | 1743 __ bind(&miss); |
2046 // Restore function name in ecx. | 1744 // Restore function name in ecx. |
2047 __ Set(ecx, Immediate(Handle<String>(name))); | 1745 __ Set(ecx, Immediate(name)); |
2048 __ bind(&name_miss); | 1746 __ bind(&name_miss); |
2049 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1747 GenerateMissBranch(); |
2050 if (maybe_result->IsFailure()) return maybe_result; | |
2051 | 1748 |
2052 // Return the generated code. | 1749 // Return the generated code. |
2053 return TryGetCode(function); | 1750 return GetCode(function); |
2054 } | 1751 } |
2055 | 1752 |
2056 | 1753 |
2057 MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( | 1754 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
2058 Object* object, | 1755 Handle<Object> object, |
2059 JSObject* holder, | 1756 Handle<JSObject> holder, |
2060 JSGlobalPropertyCell* cell, | 1757 Handle<JSGlobalPropertyCell> cell, |
2061 JSFunction* function, | 1758 Handle<JSFunction> function, |
2062 String* name) { | 1759 Handle<String> name) { |
2063 // ----------- S t a t e ------------- | 1760 // ----------- S t a t e ------------- |
2064 // -- ecx : function name | 1761 // -- ecx : function name |
2065 // -- esp[0] : return address | 1762 // -- esp[0] : return address |
2066 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1763 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
2067 // -- ... | 1764 // -- ... |
2068 // -- esp[(argc + 1) * 4] : receiver | 1765 // -- esp[(argc + 1) * 4] : receiver |
2069 // ----------------------------------- | 1766 // ----------------------------------- |
2070 | 1767 |
2071 const int argc = arguments().immediate(); | 1768 const int argc = arguments().immediate(); |
2072 | 1769 |
2073 // If the object is not a JSObject or we got an unexpected number of | 1770 // If the object is not a JSObject or we got an unexpected number of |
2074 // arguments, bail out to the regular call. | 1771 // arguments, bail out to the regular call. |
2075 if (!object->IsJSObject() || argc != 1) { | 1772 if (!object->IsJSObject() || argc != 1) { |
2076 return isolate()->heap()->undefined_value(); | 1773 return Handle<Code>::null(); |
2077 } | 1774 } |
2078 | 1775 |
2079 Label miss; | 1776 Label miss; |
2080 GenerateNameCheck(Handle<String>(name), &miss); | 1777 GenerateNameCheck(name, &miss); |
2081 | 1778 |
2082 if (cell == NULL) { | 1779 if (cell.is_null()) { |
2083 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 1780 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
2084 | |
2085 STATIC_ASSERT(kSmiTag == 0); | 1781 STATIC_ASSERT(kSmiTag == 0); |
2086 __ JumpIfSmi(edx, &miss); | 1782 __ JumpIfSmi(edx, &miss); |
2087 | 1783 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, |
2088 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, | 1784 name, &miss); |
2089 &miss); | |
2090 } else { | 1785 } else { |
2091 ASSERT(cell->value() == function); | 1786 ASSERT(cell->value() == *function); |
2092 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); | 1787 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 1788 &miss); |
2093 GenerateLoadFunctionFromCell(cell, function, &miss); | 1789 GenerateLoadFunctionFromCell(cell, function, &miss); |
2094 } | 1790 } |
2095 | 1791 |
2096 // Load the char code argument. | 1792 // Load the char code argument. |
2097 Register code = ebx; | 1793 Register code = ebx; |
2098 __ mov(code, Operand(esp, 1 * kPointerSize)); | 1794 __ mov(code, Operand(esp, 1 * kPointerSize)); |
2099 | 1795 |
2100 // Check the code is a smi. | 1796 // Check the code is a smi. |
2101 Label slow; | 1797 Label slow; |
2102 STATIC_ASSERT(kSmiTag == 0); | 1798 STATIC_ASSERT(kSmiTag == 0); |
2103 __ JumpIfNotSmi(code, &slow); | 1799 __ JumpIfNotSmi(code, &slow); |
2104 | 1800 |
2105 // Convert the smi code to uint16. | 1801 // Convert the smi code to uint16. |
2106 __ and_(code, Immediate(Smi::FromInt(0xffff))); | 1802 __ and_(code, Immediate(Smi::FromInt(0xffff))); |
2107 | 1803 |
2108 StringCharFromCodeGenerator char_from_code_generator(code, eax); | 1804 StringCharFromCodeGenerator generator(code, eax); |
2109 char_from_code_generator.GenerateFast(masm()); | 1805 generator.GenerateFast(masm()); |
2110 __ ret(2 * kPointerSize); | 1806 __ ret(2 * kPointerSize); |
2111 | 1807 |
2112 StubRuntimeCallHelper call_helper; | 1808 StubRuntimeCallHelper call_helper; |
2113 char_from_code_generator.GenerateSlow(masm(), call_helper); | 1809 generator.GenerateSlow(masm(), call_helper); |
2114 | 1810 |
2115 // Tail call the full function. We do not have to patch the receiver | 1811 // Tail call the full function. We do not have to patch the receiver |
2116 // because the function makes no use of it. | 1812 // because the function makes no use of it. |
2117 __ bind(&slow); | 1813 __ bind(&slow); |
2118 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 1814 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
2119 ? CALL_AS_FUNCTION | 1815 ? CALL_AS_FUNCTION |
2120 : CALL_AS_METHOD; | 1816 : CALL_AS_METHOD; |
2121 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 1817 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
2122 NullCallWrapper(), call_kind); | 1818 NullCallWrapper(), call_kind); |
2123 | 1819 |
2124 __ bind(&miss); | 1820 __ bind(&miss); |
2125 // ecx: function name. | 1821 // ecx: function name. |
2126 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1822 GenerateMissBranch(); |
2127 if (maybe_result->IsFailure()) return maybe_result; | |
2128 | 1823 |
2129 // Return the generated code. | 1824 // Return the generated code. |
2130 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); | 1825 return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); |
2131 } | 1826 } |
2132 | 1827 |
2133 | 1828 |
2134 MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, | 1829 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
2135 JSObject* holder, | 1830 Handle<Object> object, |
2136 JSGlobalPropertyCell* cell, | 1831 Handle<JSObject> holder, |
2137 JSFunction* function, | 1832 Handle<JSGlobalPropertyCell> cell, |
2138 String* name) { | 1833 Handle<JSFunction> function, |
| 1834 Handle<String> name) { |
2139 // ----------- S t a t e ------------- | 1835 // ----------- S t a t e ------------- |
2140 // -- ecx : name | 1836 // -- ecx : name |
2141 // -- esp[0] : return address | 1837 // -- esp[0] : return address |
2142 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1838 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
2143 // -- ... | 1839 // -- ... |
2144 // -- esp[(argc + 1) * 4] : receiver | 1840 // -- esp[(argc + 1) * 4] : receiver |
2145 // ----------------------------------- | 1841 // ----------------------------------- |
2146 | 1842 |
2147 if (!CpuFeatures::IsSupported(SSE2)) { | 1843 if (!CpuFeatures::IsSupported(SSE2)) { |
2148 return isolate()->heap()->undefined_value(); | 1844 return Handle<Code>::null(); |
2149 } | 1845 } |
2150 | 1846 |
2151 CpuFeatures::Scope use_sse2(SSE2); | 1847 CpuFeatures::Scope use_sse2(SSE2); |
2152 | 1848 |
2153 const int argc = arguments().immediate(); | 1849 const int argc = arguments().immediate(); |
2154 | 1850 |
2155 // If the object is not a JSObject or we got an unexpected number of | 1851 // If the object is not a JSObject or we got an unexpected number of |
2156 // arguments, bail out to the regular call. | 1852 // arguments, bail out to the regular call. |
2157 if (!object->IsJSObject() || argc != 1) { | 1853 if (!object->IsJSObject() || argc != 1) { |
2158 return isolate()->heap()->undefined_value(); | 1854 return Handle<Code>::null(); |
2159 } | 1855 } |
2160 | 1856 |
2161 Label miss; | 1857 Label miss; |
2162 GenerateNameCheck(Handle<String>(name), &miss); | 1858 GenerateNameCheck(name, &miss); |
2163 | 1859 |
2164 if (cell == NULL) { | 1860 if (cell.is_null()) { |
2165 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 1861 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
2166 | 1862 |
2167 STATIC_ASSERT(kSmiTag == 0); | 1863 STATIC_ASSERT(kSmiTag == 0); |
2168 __ JumpIfSmi(edx, &miss); | 1864 __ JumpIfSmi(edx, &miss); |
2169 | 1865 |
2170 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, | 1866 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, |
2171 &miss); | 1867 name, &miss); |
2172 } else { | 1868 } else { |
2173 ASSERT(cell->value() == function); | 1869 ASSERT(cell->value() == *function); |
2174 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); | 1870 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 1871 &miss); |
2175 GenerateLoadFunctionFromCell(cell, function, &miss); | 1872 GenerateLoadFunctionFromCell(cell, function, &miss); |
2176 } | 1873 } |
2177 | 1874 |
2178 // Load the (only) argument into eax. | 1875 // Load the (only) argument into eax. |
2179 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 1876 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
2180 | 1877 |
2181 // Check if the argument is a smi. | 1878 // Check if the argument is a smi. |
2182 Label smi; | 1879 Label smi; |
2183 STATIC_ASSERT(kSmiTag == 0); | 1880 STATIC_ASSERT(kSmiTag == 0); |
2184 __ JumpIfSmi(eax, &smi); | 1881 __ JumpIfSmi(eax, &smi); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2245 __ ret(2 * kPointerSize); | 1942 __ ret(2 * kPointerSize); |
2246 | 1943 |
2247 // Tail call the full function. We do not have to patch the receiver | 1944 // Tail call the full function. We do not have to patch the receiver |
2248 // because the function makes no use of it. | 1945 // because the function makes no use of it. |
2249 __ bind(&slow); | 1946 __ bind(&slow); |
2250 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 1947 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
2251 NullCallWrapper(), CALL_AS_METHOD); | 1948 NullCallWrapper(), CALL_AS_METHOD); |
2252 | 1949 |
2253 __ bind(&miss); | 1950 __ bind(&miss); |
2254 // ecx: function name. | 1951 // ecx: function name. |
2255 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1952 GenerateMissBranch(); |
2256 if (maybe_result->IsFailure()) return maybe_result; | |
2257 | 1953 |
2258 // Return the generated code. | 1954 // Return the generated code. |
2259 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); | 1955 return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); |
2260 } | 1956 } |
2261 | 1957 |
2262 | 1958 |
2263 MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object, | 1959 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
2264 JSObject* holder, | 1960 Handle<Object> object, |
2265 JSGlobalPropertyCell* cell, | 1961 Handle<JSObject> holder, |
2266 JSFunction* function, | 1962 Handle<JSGlobalPropertyCell> cell, |
2267 String* name) { | 1963 Handle<JSFunction> function, |
| 1964 Handle<String> name) { |
2268 // ----------- S t a t e ------------- | 1965 // ----------- S t a t e ------------- |
2269 // -- ecx : name | 1966 // -- ecx : name |
2270 // -- esp[0] : return address | 1967 // -- esp[0] : return address |
2271 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1968 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
2272 // -- ... | 1969 // -- ... |
2273 // -- esp[(argc + 1) * 4] : receiver | 1970 // -- esp[(argc + 1) * 4] : receiver |
2274 // ----------------------------------- | 1971 // ----------------------------------- |
2275 | 1972 |
2276 const int argc = arguments().immediate(); | 1973 const int argc = arguments().immediate(); |
2277 | 1974 |
2278 // If the object is not a JSObject or we got an unexpected number of | 1975 // If the object is not a JSObject or we got an unexpected number of |
2279 // arguments, bail out to the regular call. | 1976 // arguments, bail out to the regular call. |
2280 if (!object->IsJSObject() || argc != 1) { | 1977 if (!object->IsJSObject() || argc != 1) { |
2281 return isolate()->heap()->undefined_value(); | 1978 return Handle<Code>::null(); |
2282 } | 1979 } |
2283 | 1980 |
2284 Label miss; | 1981 Label miss; |
2285 GenerateNameCheck(Handle<String>(name), &miss); | 1982 GenerateNameCheck(name, &miss); |
2286 | 1983 |
2287 if (cell == NULL) { | 1984 if (cell.is_null()) { |
2288 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 1985 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
2289 | 1986 |
2290 STATIC_ASSERT(kSmiTag == 0); | 1987 STATIC_ASSERT(kSmiTag == 0); |
2291 __ JumpIfSmi(edx, &miss); | 1988 __ JumpIfSmi(edx, &miss); |
2292 | 1989 |
2293 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, | 1990 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, |
2294 &miss); | 1991 name, &miss); |
2295 } else { | 1992 } else { |
2296 ASSERT(cell->value() == function); | 1993 ASSERT(cell->value() == *function); |
2297 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); | 1994 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 1995 &miss); |
2298 GenerateLoadFunctionFromCell(cell, function, &miss); | 1996 GenerateLoadFunctionFromCell(cell, function, &miss); |
2299 } | 1997 } |
2300 | 1998 |
2301 // Load the (only) argument into eax. | 1999 // Load the (only) argument into eax. |
2302 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 2000 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
2303 | 2001 |
2304 // Check if the argument is a smi. | 2002 // Check if the argument is a smi. |
2305 Label not_smi; | 2003 Label not_smi; |
2306 STATIC_ASSERT(kSmiTag == 0); | 2004 STATIC_ASSERT(kSmiTag == 0); |
2307 __ JumpIfNotSmi(eax, ¬_smi); | 2005 __ JumpIfNotSmi(eax, ¬_smi); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2349 __ ret(2 * kPointerSize); | 2047 __ ret(2 * kPointerSize); |
2350 | 2048 |
2351 // Tail call the full function. We do not have to patch the receiver | 2049 // Tail call the full function. We do not have to patch the receiver |
2352 // because the function makes no use of it. | 2050 // because the function makes no use of it. |
2353 __ bind(&slow); | 2051 __ bind(&slow); |
2354 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2052 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
2355 NullCallWrapper(), CALL_AS_METHOD); | 2053 NullCallWrapper(), CALL_AS_METHOD); |
2356 | 2054 |
2357 __ bind(&miss); | 2055 __ bind(&miss); |
2358 // ecx: function name. | 2056 // ecx: function name. |
2359 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2057 GenerateMissBranch(); |
2360 if (maybe_result->IsFailure()) return maybe_result; | |
2361 | 2058 |
2362 // Return the generated code. | 2059 // Return the generated code. |
2363 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); | 2060 return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); |
2364 } | 2061 } |
2365 | 2062 |
2366 | 2063 |
2367 MaybeObject* CallStubCompiler::CompileFastApiCall( | 2064 Handle<Code> CallStubCompiler::CompileFastApiCall( |
2368 const CallOptimization& optimization, | 2065 const CallOptimization& optimization, |
2369 Object* object, | 2066 Handle<Object> object, |
2370 JSObject* holder, | 2067 Handle<JSObject> holder, |
2371 JSGlobalPropertyCell* cell, | 2068 Handle<JSGlobalPropertyCell> cell, |
2372 JSFunction* function, | 2069 Handle<JSFunction> function, |
2373 String* name) { | 2070 Handle<String> name) { |
2374 ASSERT(optimization.is_simple_api_call()); | 2071 ASSERT(optimization.is_simple_api_call()); |
2375 // Bail out if object is a global object as we don't want to | 2072 // Bail out if object is a global object as we don't want to |
2376 // repatch it to global receiver. | 2073 // repatch it to global receiver. |
2377 if (object->IsGlobalObject()) return heap()->undefined_value(); | 2074 if (object->IsGlobalObject()) return Handle<Code>::null(); |
2378 if (cell != NULL) return heap()->undefined_value(); | 2075 if (!cell.is_null()) return Handle<Code>::null(); |
2379 if (!object->IsJSObject()) return heap()->undefined_value(); | 2076 if (!object->IsJSObject()) return Handle<Code>::null(); |
2380 int depth = optimization.GetPrototypeDepthOfExpectedType( | 2077 int depth = optimization.GetPrototypeDepthOfExpectedType( |
2381 JSObject::cast(object), holder); | 2078 Handle<JSObject>::cast(object), holder); |
2382 if (depth == kInvalidProtoDepth) return heap()->undefined_value(); | 2079 if (depth == kInvalidProtoDepth) return Handle<Code>::null(); |
2383 | 2080 |
2384 Label miss, miss_before_stack_reserved; | 2081 Label miss, miss_before_stack_reserved; |
2385 | 2082 |
2386 GenerateNameCheck(Handle<String>(name), &miss_before_stack_reserved); | 2083 GenerateNameCheck(name, &miss_before_stack_reserved); |
2387 | 2084 |
2388 // Get the receiver from the stack. | 2085 // Get the receiver from the stack. |
2389 const int argc = arguments().immediate(); | 2086 const int argc = arguments().immediate(); |
2390 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2087 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2391 | 2088 |
2392 // Check that the receiver isn't a smi. | 2089 // Check that the receiver isn't a smi. |
2393 __ JumpIfSmi(edx, &miss_before_stack_reserved); | 2090 __ JumpIfSmi(edx, &miss_before_stack_reserved); |
2394 | 2091 |
2395 Counters* counters = isolate()->counters(); | 2092 Counters* counters = isolate()->counters(); |
2396 __ IncrementCounter(counters->call_const(), 1); | 2093 __ IncrementCounter(counters->call_const(), 1); |
2397 __ IncrementCounter(counters->call_const_fast_api(), 1); | 2094 __ IncrementCounter(counters->call_const_fast_api(), 1); |
2398 | 2095 |
2399 // Allocate space for v8::Arguments implicit values. Must be initialized | 2096 // Allocate space for v8::Arguments implicit values. Must be initialized |
2400 // before calling any runtime function. | 2097 // before calling any runtime function. |
2401 __ sub(esp, Immediate(kFastApiCallArguments * kPointerSize)); | 2098 __ sub(esp, Immediate(kFastApiCallArguments * kPointerSize)); |
2402 | 2099 |
2403 // Check that the maps haven't changed and find a Holder as a side effect. | 2100 // Check that the maps haven't changed and find a Holder as a side effect. |
2404 CheckPrototypes(JSObject::cast(object), edx, holder, | 2101 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, |
2405 ebx, eax, edi, name, depth, &miss); | 2102 name, depth, &miss); |
2406 | 2103 |
2407 // Move the return address on top of the stack. | 2104 // Move the return address on top of the stack. |
2408 __ mov(eax, Operand(esp, 3 * kPointerSize)); | 2105 __ mov(eax, Operand(esp, 3 * kPointerSize)); |
2409 __ mov(Operand(esp, 0 * kPointerSize), eax); | 2106 __ mov(Operand(esp, 0 * kPointerSize), eax); |
2410 | 2107 |
2411 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains | 2108 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains |
2412 // duplicate of return address and will be overwritten. | 2109 // duplicate of return address and will be overwritten. |
2413 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc); | 2110 GenerateFastApiCall(masm(), optimization, argc); |
2414 if (result->IsFailure()) return result; | |
2415 | 2111 |
2416 __ bind(&miss); | 2112 __ bind(&miss); |
2417 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); | 2113 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize)); |
2418 | 2114 |
2419 __ bind(&miss_before_stack_reserved); | 2115 __ bind(&miss_before_stack_reserved); |
2420 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2116 GenerateMissBranch(); |
2421 if (maybe_result->IsFailure()) return maybe_result; | |
2422 | 2117 |
2423 // Return the generated code. | 2118 // Return the generated code. |
2424 return TryGetCode(function); | 2119 return GetCode(function); |
2425 } | 2120 } |
2426 | 2121 |
2427 | 2122 |
2428 MaybeObject* CallStubCompiler::CompileCallConstant( | 2123 Handle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object, |
2429 Object* object, | 2124 Handle<JSObject> holder, |
2430 JSObject* holder, | 2125 Handle<JSFunction> function, |
2431 JSFunction* function, | 2126 Handle<String> name, |
2432 String* name, | 2127 CheckType check) { |
2433 CheckType check) { | |
2434 // ----------- S t a t e ------------- | 2128 // ----------- S t a t e ------------- |
2435 // -- ecx : name | 2129 // -- ecx : name |
2436 // -- esp[0] : return address | 2130 // -- esp[0] : return address |
2437 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2131 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
2438 // -- ... | 2132 // -- ... |
2439 // -- esp[(argc + 1) * 4] : receiver | 2133 // -- esp[(argc + 1) * 4] : receiver |
2440 // ----------------------------------- | 2134 // ----------------------------------- |
2441 | 2135 |
2442 if (HasCustomCallGenerator(function)) { | 2136 if (HasCustomCallGenerator(function)) { |
2443 MaybeObject* maybe_result = CompileCustomCall( | 2137 Handle<Code> code = CompileCustomCall(object, holder, |
2444 object, holder, NULL, function, name); | 2138 Handle<JSGlobalPropertyCell>::null(), |
2445 Object* result; | 2139 function, name); |
2446 if (!maybe_result->ToObject(&result)) return maybe_result; | 2140 // A null handle means bail out to the regular compiler code below. |
2447 // undefined means bail out to regular compiler. | 2141 if (!code.is_null()) return code; |
2448 if (!result->IsUndefined()) return result; | |
2449 } | 2142 } |
2450 | 2143 |
2451 Label miss; | 2144 Label miss; |
2452 | 2145 GenerateNameCheck(name, &miss); |
2453 GenerateNameCheck(Handle<String>(name), &miss); | |
2454 | 2146 |
2455 // Get the receiver from the stack. | 2147 // Get the receiver from the stack. |
2456 const int argc = arguments().immediate(); | 2148 const int argc = arguments().immediate(); |
2457 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2149 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2458 | 2150 |
2459 // Check that the receiver isn't a smi. | 2151 // Check that the receiver isn't a smi. |
2460 if (check != NUMBER_CHECK) { | 2152 if (check != NUMBER_CHECK) { |
2461 __ JumpIfSmi(edx, &miss); | 2153 __ JumpIfSmi(edx, &miss); |
2462 } | 2154 } |
2463 | 2155 |
2464 // Make sure that it's okay not to patch the on stack receiver | 2156 // Make sure that it's okay not to patch the on stack receiver |
2465 // unless we're doing a receiver map check. | 2157 // unless we're doing a receiver map check. |
2466 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2158 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
2467 | |
2468 SharedFunctionInfo* function_info = function->shared(); | |
2469 switch (check) { | 2159 switch (check) { |
2470 case RECEIVER_MAP_CHECK: | 2160 case RECEIVER_MAP_CHECK: |
2471 __ IncrementCounter(isolate()->counters()->call_const(), 1); | 2161 __ IncrementCounter(isolate()->counters()->call_const(), 1); |
2472 | 2162 |
2473 // Check that the maps haven't changed. | 2163 // Check that the maps haven't changed. |
2474 CheckPrototypes(JSObject::cast(object), edx, holder, | 2164 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, |
2475 ebx, eax, edi, name, &miss); | 2165 edi, name, &miss); |
2476 | 2166 |
2477 // Patch the receiver on the stack with the global proxy if | 2167 // Patch the receiver on the stack with the global proxy if |
2478 // necessary. | 2168 // necessary. |
2479 if (object->IsGlobalObject()) { | 2169 if (object->IsGlobalObject()) { |
2480 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2170 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
2481 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 2171 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
2482 } | 2172 } |
2483 break; | 2173 break; |
2484 | 2174 |
2485 case STRING_CHECK: | 2175 case STRING_CHECK: |
2486 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2176 if (function->IsBuiltin() || function->shared()->strict_mode()) { |
2487 // Calling non-strict non-builtins with a value as the receiver | |
2488 // requires boxing. | |
2489 __ jmp(&miss); | |
2490 } else { | |
2491 // Check that the object is a string or a symbol. | 2177 // Check that the object is a string or a symbol. |
2492 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax); | 2178 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax); |
2493 __ j(above_equal, &miss); | 2179 __ j(above_equal, &miss); |
2494 // Check that the maps starting from the prototype haven't changed. | 2180 // Check that the maps starting from the prototype haven't changed. |
2495 GenerateDirectLoadGlobalFunctionPrototype( | 2181 GenerateDirectLoadGlobalFunctionPrototype( |
2496 masm(), Context::STRING_FUNCTION_INDEX, eax, &miss); | 2182 masm(), Context::STRING_FUNCTION_INDEX, eax, &miss); |
2497 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 2183 CheckPrototypes( |
2498 ebx, edx, edi, name, &miss); | 2184 Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
| 2185 eax, holder, ebx, edx, edi, name, &miss); |
| 2186 } else { |
| 2187 // Calling non-strict non-builtins with a value as the receiver |
| 2188 // requires boxing. |
| 2189 __ jmp(&miss); |
2499 } | 2190 } |
2500 break; | 2191 break; |
2501 | 2192 |
2502 case NUMBER_CHECK: { | 2193 case NUMBER_CHECK: |
2503 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2194 if (function->IsBuiltin() || function->shared()->strict_mode()) { |
2504 // Calling non-strict non-builtins with a value as the receiver | |
2505 // requires boxing. | |
2506 __ jmp(&miss); | |
2507 } else { | |
2508 Label fast; | 2195 Label fast; |
2509 // Check that the object is a smi or a heap number. | 2196 // Check that the object is a smi or a heap number. |
2510 __ JumpIfSmi(edx, &fast); | 2197 __ JumpIfSmi(edx, &fast); |
2511 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); | 2198 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); |
2512 __ j(not_equal, &miss); | 2199 __ j(not_equal, &miss); |
2513 __ bind(&fast); | 2200 __ bind(&fast); |
2514 // Check that the maps starting from the prototype haven't changed. | 2201 // Check that the maps starting from the prototype haven't changed. |
2515 GenerateDirectLoadGlobalFunctionPrototype( | 2202 GenerateDirectLoadGlobalFunctionPrototype( |
2516 masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss); | 2203 masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss); |
2517 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 2204 CheckPrototypes( |
2518 ebx, edx, edi, name, &miss); | 2205 Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
2519 } | 2206 eax, holder, ebx, edx, edi, name, &miss); |
2520 break; | 2207 } else { |
2521 } | |
2522 | |
2523 case BOOLEAN_CHECK: { | |
2524 if (!function->IsBuiltin() && !function_info->strict_mode()) { | |
2525 // Calling non-strict non-builtins with a value as the receiver | 2208 // Calling non-strict non-builtins with a value as the receiver |
2526 // requires boxing. | 2209 // requires boxing. |
2527 __ jmp(&miss); | 2210 __ jmp(&miss); |
2528 } else { | 2211 } |
| 2212 break; |
| 2213 |
| 2214 case BOOLEAN_CHECK: |
| 2215 if (function->IsBuiltin() || function->shared()->strict_mode()) { |
2529 Label fast; | 2216 Label fast; |
2530 // Check that the object is a boolean. | 2217 // Check that the object is a boolean. |
2531 __ cmp(edx, factory()->true_value()); | 2218 __ cmp(edx, factory()->true_value()); |
2532 __ j(equal, &fast); | 2219 __ j(equal, &fast); |
2533 __ cmp(edx, factory()->false_value()); | 2220 __ cmp(edx, factory()->false_value()); |
2534 __ j(not_equal, &miss); | 2221 __ j(not_equal, &miss); |
2535 __ bind(&fast); | 2222 __ bind(&fast); |
2536 // Check that the maps starting from the prototype haven't changed. | 2223 // Check that the maps starting from the prototype haven't changed. |
2537 GenerateDirectLoadGlobalFunctionPrototype( | 2224 GenerateDirectLoadGlobalFunctionPrototype( |
2538 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); | 2225 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); |
2539 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 2226 CheckPrototypes( |
2540 ebx, edx, edi, name, &miss); | 2227 Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
| 2228 eax, holder, ebx, edx, edi, name, &miss); |
| 2229 } else { |
| 2230 // Calling non-strict non-builtins with a value as the receiver |
| 2231 // requires boxing. |
| 2232 __ jmp(&miss); |
2541 } | 2233 } |
2542 break; | 2234 break; |
2543 } | |
2544 | |
2545 default: | |
2546 UNREACHABLE(); | |
2547 } | 2235 } |
2548 | 2236 |
2549 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2237 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
2550 ? CALL_AS_FUNCTION | 2238 ? CALL_AS_FUNCTION |
2551 : CALL_AS_METHOD; | 2239 : CALL_AS_METHOD; |
2552 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, | 2240 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
2553 NullCallWrapper(), call_kind); | 2241 NullCallWrapper(), call_kind); |
2554 | 2242 |
2555 // Handle call cache miss. | 2243 // Handle call cache miss. |
2556 __ bind(&miss); | 2244 __ bind(&miss); |
2557 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2245 GenerateMissBranch(); |
2558 if (maybe_result->IsFailure()) return maybe_result; | |
2559 | 2246 |
2560 // Return the generated code. | 2247 // Return the generated code. |
2561 return TryGetCode(function); | 2248 return GetCode(function); |
2562 } | 2249 } |
2563 | 2250 |
2564 | 2251 |
2565 MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, | 2252 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
2566 JSObject* holder, | 2253 Handle<JSObject> holder, |
2567 String* name) { | 2254 Handle<String> name) { |
2568 // ----------- S t a t e ------------- | 2255 // ----------- S t a t e ------------- |
2569 // -- ecx : name | 2256 // -- ecx : name |
2570 // -- esp[0] : return address | 2257 // -- esp[0] : return address |
2571 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2258 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
2572 // -- ... | 2259 // -- ... |
2573 // -- esp[(argc + 1) * 4] : receiver | 2260 // -- esp[(argc + 1) * 4] : receiver |
2574 // ----------------------------------- | 2261 // ----------------------------------- |
2575 Label miss; | 2262 Label miss; |
2576 | 2263 |
2577 GenerateNameCheck(Handle<String>(name), &miss); | 2264 GenerateNameCheck(name, &miss); |
2578 | 2265 |
2579 // Get the number of arguments. | 2266 // Get the number of arguments. |
2580 const int argc = arguments().immediate(); | 2267 const int argc = arguments().immediate(); |
2581 | 2268 |
2582 LookupResult lookup(isolate()); | 2269 LookupResult lookup(isolate()); |
2583 LookupPostInterceptor(holder, name, &lookup); | 2270 LookupPostInterceptor(holder, name, &lookup); |
2584 | 2271 |
2585 // Get the receiver from the stack. | 2272 // Get the receiver from the stack. |
2586 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2273 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2587 | 2274 |
2588 CallInterceptorCompiler compiler(this, arguments(), ecx, extra_state_); | 2275 CallInterceptorCompiler compiler(this, arguments(), ecx, extra_state_); |
2589 MaybeObject* result = compiler.Compile(masm(), | 2276 compiler.Compile(masm(), object, holder, name, &lookup, edx, ebx, edi, eax, |
2590 object, | 2277 &miss); |
2591 holder, | |
2592 name, | |
2593 &lookup, | |
2594 edx, | |
2595 ebx, | |
2596 edi, | |
2597 eax, | |
2598 &miss); | |
2599 if (result->IsFailure()) return result; | |
2600 | 2278 |
2601 // Restore receiver. | 2279 // Restore receiver. |
2602 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2280 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2603 | 2281 |
2604 // Check that the function really is a function. | 2282 // Check that the function really is a function. |
2605 __ JumpIfSmi(eax, &miss); | 2283 __ JumpIfSmi(eax, &miss); |
2606 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); | 2284 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); |
2607 __ j(not_equal, &miss); | 2285 __ j(not_equal, &miss); |
2608 | 2286 |
2609 // Patch the receiver on the stack with the global proxy if | 2287 // Patch the receiver on the stack with the global proxy if |
2610 // necessary. | 2288 // necessary. |
2611 if (object->IsGlobalObject()) { | 2289 if (object->IsGlobalObject()) { |
2612 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2290 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
2613 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 2291 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
2614 } | 2292 } |
2615 | 2293 |
2616 // Invoke the function. | 2294 // Invoke the function. |
2617 __ mov(edi, eax); | 2295 __ mov(edi, eax); |
2618 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2296 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
2619 ? CALL_AS_FUNCTION | 2297 ? CALL_AS_FUNCTION |
2620 : CALL_AS_METHOD; | 2298 : CALL_AS_METHOD; |
2621 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, | 2299 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION, |
2622 NullCallWrapper(), call_kind); | 2300 NullCallWrapper(), call_kind); |
2623 | 2301 |
2624 // Handle load cache miss. | 2302 // Handle load cache miss. |
2625 __ bind(&miss); | 2303 __ bind(&miss); |
2626 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2304 GenerateMissBranch(); |
2627 if (maybe_result->IsFailure()) return maybe_result; | |
2628 | 2305 |
2629 // Return the generated code. | 2306 // Return the generated code. |
2630 return TryGetCode(INTERCEPTOR, name); | 2307 return GetCode(INTERCEPTOR, name); |
2631 } | 2308 } |
2632 | 2309 |
2633 | 2310 |
2634 MaybeObject* CallStubCompiler::CompileCallGlobal( | 2311 Handle<Code> CallStubCompiler::CompileCallGlobal( |
2635 JSObject* object, | 2312 Handle<JSObject> object, |
2636 GlobalObject* holder, | 2313 Handle<GlobalObject> holder, |
2637 JSGlobalPropertyCell* cell, | 2314 Handle<JSGlobalPropertyCell> cell, |
2638 JSFunction* function, | 2315 Handle<JSFunction> function, |
2639 String* name) { | 2316 Handle<String> name) { |
2640 // ----------- S t a t e ------------- | 2317 // ----------- S t a t e ------------- |
2641 // -- ecx : name | 2318 // -- ecx : name |
2642 // -- esp[0] : return address | 2319 // -- esp[0] : return address |
2643 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2320 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
2644 // -- ... | 2321 // -- ... |
2645 // -- esp[(argc + 1) * 4] : receiver | 2322 // -- esp[(argc + 1) * 4] : receiver |
2646 // ----------------------------------- | 2323 // ----------------------------------- |
2647 | 2324 |
2648 if (HasCustomCallGenerator(function)) { | 2325 if (HasCustomCallGenerator(function)) { |
2649 MaybeObject* maybe_result = CompileCustomCall( | 2326 Handle<Code> code = CompileCustomCall(object, holder, cell, function, name); |
2650 object, holder, cell, function, name); | 2327 // A null handle means bail out to the regular compiler code below. |
2651 Object* result; | 2328 if (!code.is_null()) return code; |
2652 if (!maybe_result->ToObject(&result)) return maybe_result; | |
2653 // undefined means bail out to regular compiler. | |
2654 if (!result->IsUndefined()) return result; | |
2655 } | 2329 } |
2656 | 2330 |
2657 Label miss; | 2331 Label miss; |
2658 | 2332 GenerateNameCheck(name, &miss); |
2659 GenerateNameCheck(Handle<String>(name), &miss); | |
2660 | 2333 |
2661 // Get the number of arguments. | 2334 // Get the number of arguments. |
2662 const int argc = arguments().immediate(); | 2335 const int argc = arguments().immediate(); |
2663 | |
2664 GenerateGlobalReceiverCheck(object, holder, name, &miss); | 2336 GenerateGlobalReceiverCheck(object, holder, name, &miss); |
2665 | |
2666 GenerateLoadFunctionFromCell(cell, function, &miss); | 2337 GenerateLoadFunctionFromCell(cell, function, &miss); |
2667 | 2338 |
2668 // Patch the receiver on the stack with the global proxy. | 2339 // Patch the receiver on the stack with the global proxy. |
2669 if (object->IsGlobalObject()) { | 2340 if (object->IsGlobalObject()) { |
2670 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2341 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
2671 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 2342 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
2672 } | 2343 } |
2673 | 2344 |
2674 // Setup the context (function already in edi). | 2345 // Setup the context (function already in edi). |
2675 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 2346 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
2676 | 2347 |
2677 // Jump to the cached code (tail call). | 2348 // Jump to the cached code (tail call). |
2678 Counters* counters = isolate()->counters(); | 2349 Counters* counters = isolate()->counters(); |
2679 __ IncrementCounter(counters->call_global_inline(), 1); | 2350 __ IncrementCounter(counters->call_global_inline(), 1); |
2680 ParameterCount expected(function->shared()->formal_parameter_count()); | 2351 ParameterCount expected(function->shared()->formal_parameter_count()); |
2681 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2352 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
2682 ? CALL_AS_FUNCTION | 2353 ? CALL_AS_FUNCTION |
2683 : CALL_AS_METHOD; | 2354 : CALL_AS_METHOD; |
2684 // We call indirectly through the code field in the function to | 2355 // We call indirectly through the code field in the function to |
2685 // allow recompilation to take effect without changing any of the | 2356 // allow recompilation to take effect without changing any of the |
2686 // call sites. | 2357 // call sites. |
2687 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), | 2358 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), |
2688 expected, arguments(), JUMP_FUNCTION, | 2359 expected, arguments(), JUMP_FUNCTION, |
2689 NullCallWrapper(), call_kind); | 2360 NullCallWrapper(), call_kind); |
2690 | 2361 |
2691 // Handle call cache miss. | 2362 // Handle call cache miss. |
2692 __ bind(&miss); | 2363 __ bind(&miss); |
2693 __ IncrementCounter(counters->call_global_inline_miss(), 1); | 2364 __ IncrementCounter(counters->call_global_inline_miss(), 1); |
2694 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2365 GenerateMissBranch(); |
2695 if (maybe_result->IsFailure()) return maybe_result; | |
2696 | 2366 |
2697 // Return the generated code. | 2367 // Return the generated code. |
2698 return TryGetCode(NORMAL, name); | 2368 return GetCode(NORMAL, name); |
2699 } | 2369 } |
2700 | 2370 |
2701 | 2371 |
2702 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, | 2372 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, |
2703 int index, | 2373 int index, |
2704 Handle<Map> transition, | 2374 Handle<Map> transition, |
2705 Handle<String> name) { | 2375 Handle<String> name) { |
2706 // ----------- S t a t e ------------- | 2376 // ----------- S t a t e ------------- |
2707 // -- eax : value | 2377 // -- eax : value |
2708 // -- ecx : name | 2378 // -- ecx : name |
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3032 | 2702 |
3033 GenerateLoadField(object, holder, eax, ebx, edx, edi, index, name, &miss); | 2703 GenerateLoadField(object, holder, eax, ebx, edx, edi, index, name, &miss); |
3034 __ bind(&miss); | 2704 __ bind(&miss); |
3035 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2705 GenerateLoadMiss(masm(), Code::LOAD_IC); |
3036 | 2706 |
3037 // Return the generated code. | 2707 // Return the generated code. |
3038 return GetCode(FIELD, name); | 2708 return GetCode(FIELD, name); |
3039 } | 2709 } |
3040 | 2710 |
3041 | 2711 |
3042 MaybeObject* LoadStubCompiler::CompileLoadCallback(String* name, | 2712 Handle<Code> LoadStubCompiler::CompileLoadCallback( |
3043 JSObject* object, | 2713 Handle<String> name, |
3044 JSObject* holder, | 2714 Handle<JSObject> object, |
3045 AccessorInfo* callback) { | 2715 Handle<JSObject> holder, |
| 2716 Handle<AccessorInfo> callback) { |
3046 // ----------- S t a t e ------------- | 2717 // ----------- S t a t e ------------- |
3047 // -- eax : receiver | 2718 // -- eax : receiver |
3048 // -- ecx : name | 2719 // -- ecx : name |
3049 // -- esp[0] : return address | 2720 // -- esp[0] : return address |
3050 // ----------------------------------- | 2721 // ----------------------------------- |
3051 Label miss; | 2722 Label miss; |
3052 | 2723 |
3053 MaybeObject* result = GenerateLoadCallback(object, holder, eax, ecx, ebx, edx, | 2724 GenerateLoadCallback(object, holder, eax, ecx, ebx, edx, edi, callback, |
3054 edi, callback, name, &miss); | 2725 name, &miss); |
3055 if (result->IsFailure()) { | |
3056 miss.Unuse(); | |
3057 return result; | |
3058 } | |
3059 | |
3060 __ bind(&miss); | 2726 __ bind(&miss); |
3061 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2727 GenerateLoadMiss(masm(), Code::LOAD_IC); |
3062 | 2728 |
3063 // Return the generated code. | 2729 // Return the generated code. |
3064 return TryGetCode(CALLBACKS, name); | 2730 return GetCode(CALLBACKS, name); |
3065 } | 2731 } |
3066 | 2732 |
3067 | 2733 |
3068 Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, | 2734 Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, |
3069 Handle<JSObject> holder, | 2735 Handle<JSObject> holder, |
3070 Handle<Object> value, | 2736 Handle<Object> value, |
3071 Handle<String> name) { | 2737 Handle<String> name) { |
3072 // ----------- S t a t e ------------- | 2738 // ----------- S t a t e ------------- |
3073 // -- eax : receiver | 2739 // -- eax : receiver |
3074 // -- ecx : name | 2740 // -- ecx : name |
3075 // -- esp[0] : return address | 2741 // -- esp[0] : return address |
3076 // ----------------------------------- | 2742 // ----------------------------------- |
3077 Label miss; | 2743 Label miss; |
3078 | 2744 |
3079 GenerateLoadConstant(object, holder, eax, ebx, edx, edi, value, name, &miss); | 2745 GenerateLoadConstant(object, holder, eax, ebx, edx, edi, value, name, &miss); |
3080 __ bind(&miss); | 2746 __ bind(&miss); |
3081 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2747 GenerateLoadMiss(masm(), Code::LOAD_IC); |
3082 | 2748 |
3083 // Return the generated code. | 2749 // Return the generated code. |
3084 return GetCode(CONSTANT_FUNCTION, name); | 2750 return GetCode(CONSTANT_FUNCTION, name); |
3085 } | 2751 } |
3086 | 2752 |
3087 | 2753 |
3088 MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 2754 Handle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> receiver, |
3089 JSObject* holder, | 2755 Handle<JSObject> holder, |
3090 String* name) { | 2756 Handle<String> name) { |
3091 // ----------- S t a t e ------------- | 2757 // ----------- S t a t e ------------- |
3092 // -- eax : receiver | 2758 // -- eax : receiver |
3093 // -- ecx : name | 2759 // -- ecx : name |
3094 // -- esp[0] : return address | 2760 // -- esp[0] : return address |
3095 // ----------------------------------- | 2761 // ----------------------------------- |
3096 Label miss; | 2762 Label miss; |
3097 | 2763 |
3098 LookupResult lookup(isolate()); | 2764 LookupResult lookup(isolate()); |
3099 LookupPostInterceptor(holder, name, &lookup); | 2765 LookupPostInterceptor(holder, name, &lookup); |
3100 | 2766 |
3101 // TODO(368): Compile in the whole chain: all the interceptors in | 2767 // TODO(368): Compile in the whole chain: all the interceptors in |
3102 // prototypes and ultimate answer. | 2768 // prototypes and ultimate answer. |
3103 GenerateLoadInterceptor(receiver, | 2769 GenerateLoadInterceptor(receiver, holder, &lookup, eax, ecx, edx, ebx, edi, |
3104 holder, | 2770 name, &miss); |
3105 &lookup, | |
3106 eax, | |
3107 ecx, | |
3108 edx, | |
3109 ebx, | |
3110 edi, | |
3111 name, | |
3112 &miss); | |
3113 | 2771 |
3114 __ bind(&miss); | 2772 __ bind(&miss); |
3115 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2773 GenerateLoadMiss(masm(), Code::LOAD_IC); |
3116 | 2774 |
3117 // Return the generated code. | 2775 // Return the generated code. |
3118 return TryGetCode(INTERCEPTOR, name); | 2776 return GetCode(INTERCEPTOR, name); |
3119 } | 2777 } |
3120 | 2778 |
3121 | 2779 |
3122 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 2780 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
3123 Handle<JSObject> object, | 2781 Handle<JSObject> object, |
3124 Handle<GlobalObject> holder, | 2782 Handle<GlobalObject> holder, |
3125 Handle<JSGlobalPropertyCell> cell, | 2783 Handle<JSGlobalPropertyCell> cell, |
3126 Handle<String> name, | 2784 Handle<String> name, |
3127 bool is_dont_delete) { | 2785 bool is_dont_delete) { |
3128 // ----------- S t a t e ------------- | 2786 // ----------- S t a t e ------------- |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3195 | 2853 |
3196 __ bind(&miss); | 2854 __ bind(&miss); |
3197 __ DecrementCounter(counters->keyed_load_field(), 1); | 2855 __ DecrementCounter(counters->keyed_load_field(), 1); |
3198 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2856 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3199 | 2857 |
3200 // Return the generated code. | 2858 // Return the generated code. |
3201 return GetCode(FIELD, name); | 2859 return GetCode(FIELD, name); |
3202 } | 2860 } |
3203 | 2861 |
3204 | 2862 |
3205 MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( | 2863 Handle<Code> KeyedLoadStubCompiler::CompileLoadCallback( |
3206 String* name, | 2864 Handle<String> name, |
3207 JSObject* receiver, | 2865 Handle<JSObject> receiver, |
3208 JSObject* holder, | 2866 Handle<JSObject> holder, |
3209 AccessorInfo* callback) { | 2867 Handle<AccessorInfo> callback) { |
3210 // ----------- S t a t e ------------- | 2868 // ----------- S t a t e ------------- |
3211 // -- eax : key | 2869 // -- eax : key |
3212 // -- edx : receiver | 2870 // -- edx : receiver |
3213 // -- esp[0] : return address | 2871 // -- esp[0] : return address |
3214 // ----------------------------------- | 2872 // ----------------------------------- |
3215 Label miss; | 2873 Label miss; |
3216 | 2874 |
3217 Counters* counters = isolate()->counters(); | 2875 Counters* counters = isolate()->counters(); |
3218 __ IncrementCounter(counters->keyed_load_callback(), 1); | 2876 __ IncrementCounter(counters->keyed_load_callback(), 1); |
3219 | 2877 |
3220 // Check that the name has not changed. | 2878 // Check that the name has not changed. |
3221 __ cmp(eax, Immediate(Handle<String>(name))); | 2879 __ cmp(eax, Immediate(name)); |
3222 __ j(not_equal, &miss); | 2880 __ j(not_equal, &miss); |
3223 | 2881 |
3224 MaybeObject* result = GenerateLoadCallback(receiver, holder, edx, eax, ebx, | 2882 GenerateLoadCallback(receiver, holder, edx, eax, ebx, ecx, edi, callback, |
3225 ecx, edi, callback, name, &miss); | 2883 name, &miss); |
3226 if (result->IsFailure()) { | |
3227 miss.Unuse(); | |
3228 return result; | |
3229 } | |
3230 | 2884 |
3231 __ bind(&miss); | 2885 __ bind(&miss); |
3232 | |
3233 __ DecrementCounter(counters->keyed_load_callback(), 1); | 2886 __ DecrementCounter(counters->keyed_load_callback(), 1); |
3234 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2887 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3235 | 2888 |
3236 // Return the generated code. | 2889 // Return the generated code. |
3237 return TryGetCode(CALLBACKS, name); | 2890 return GetCode(CALLBACKS, name); |
3238 } | 2891 } |
3239 | 2892 |
3240 | 2893 |
3241 Handle<Code> KeyedLoadStubCompiler::CompileLoadConstant( | 2894 Handle<Code> KeyedLoadStubCompiler::CompileLoadConstant( |
3242 Handle<String> name, | 2895 Handle<String> name, |
3243 Handle<JSObject> receiver, | 2896 Handle<JSObject> receiver, |
3244 Handle<JSObject> holder, | 2897 Handle<JSObject> holder, |
3245 Handle<Object> value) { | 2898 Handle<Object> value) { |
3246 // ----------- S t a t e ------------- | 2899 // ----------- S t a t e ------------- |
3247 // -- eax : key | 2900 // -- eax : key |
(...skipping 13 matching lines...) Expand all Loading... |
3261 receiver, holder, edx, ebx, ecx, edi, value, name, &miss); | 2914 receiver, holder, edx, ebx, ecx, edi, value, name, &miss); |
3262 __ bind(&miss); | 2915 __ bind(&miss); |
3263 __ DecrementCounter(counters->keyed_load_constant_function(), 1); | 2916 __ DecrementCounter(counters->keyed_load_constant_function(), 1); |
3264 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2917 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3265 | 2918 |
3266 // Return the generated code. | 2919 // Return the generated code. |
3267 return GetCode(CONSTANT_FUNCTION, name); | 2920 return GetCode(CONSTANT_FUNCTION, name); |
3268 } | 2921 } |
3269 | 2922 |
3270 | 2923 |
3271 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 2924 Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor( |
3272 JSObject* holder, | 2925 Handle<JSObject> receiver, |
3273 String* name) { | 2926 Handle<JSObject> holder, |
| 2927 Handle<String> name) { |
3274 // ----------- S t a t e ------------- | 2928 // ----------- S t a t e ------------- |
3275 // -- eax : key | 2929 // -- eax : key |
3276 // -- edx : receiver | 2930 // -- edx : receiver |
3277 // -- esp[0] : return address | 2931 // -- esp[0] : return address |
3278 // ----------------------------------- | 2932 // ----------------------------------- |
3279 Label miss; | 2933 Label miss; |
3280 | 2934 |
3281 Counters* counters = isolate()->counters(); | 2935 Counters* counters = isolate()->counters(); |
3282 __ IncrementCounter(counters->keyed_load_interceptor(), 1); | 2936 __ IncrementCounter(counters->keyed_load_interceptor(), 1); |
3283 | 2937 |
3284 // Check that the name has not changed. | 2938 // Check that the name has not changed. |
3285 __ cmp(eax, Immediate(Handle<String>(name))); | 2939 __ cmp(eax, Immediate(name)); |
3286 __ j(not_equal, &miss); | 2940 __ j(not_equal, &miss); |
3287 | 2941 |
3288 LookupResult lookup(isolate()); | 2942 LookupResult lookup(isolate()); |
3289 LookupPostInterceptor(holder, name, &lookup); | 2943 LookupPostInterceptor(holder, name, &lookup); |
3290 GenerateLoadInterceptor(receiver, | 2944 GenerateLoadInterceptor(receiver, holder, &lookup, edx, eax, ecx, ebx, edi, |
3291 holder, | 2945 name, &miss); |
3292 &lookup, | |
3293 edx, | |
3294 eax, | |
3295 ecx, | |
3296 ebx, | |
3297 edi, | |
3298 name, | |
3299 &miss); | |
3300 __ bind(&miss); | 2946 __ bind(&miss); |
3301 __ DecrementCounter(counters->keyed_load_interceptor(), 1); | 2947 __ DecrementCounter(counters->keyed_load_interceptor(), 1); |
3302 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2948 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3303 | 2949 |
3304 // Return the generated code. | 2950 // Return the generated code. |
3305 return TryGetCode(INTERCEPTOR, name); | 2951 return GetCode(INTERCEPTOR, name); |
3306 } | 2952 } |
3307 | 2953 |
3308 | 2954 |
3309 Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( | 2955 Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( |
3310 Handle<String> name) { | 2956 Handle<String> name) { |
3311 // ----------- S t a t e ------------- | 2957 // ----------- S t a t e ------------- |
3312 // -- eax : key | 2958 // -- eax : key |
3313 // -- edx : receiver | 2959 // -- edx : receiver |
3314 // -- esp[0] : return address | 2960 // -- esp[0] : return address |
3315 // ----------------------------------- | 2961 // ----------------------------------- |
(...skipping 893 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4209 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); | 3855 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
4210 __ jmp(ic_miss, RelocInfo::CODE_TARGET); | 3856 __ jmp(ic_miss, RelocInfo::CODE_TARGET); |
4211 } | 3857 } |
4212 | 3858 |
4213 | 3859 |
4214 #undef __ | 3860 #undef __ |
4215 | 3861 |
4216 } } // namespace v8::internal | 3862 } } // namespace v8::internal |
4217 | 3863 |
4218 #endif // V8_TARGET_ARCH_IA32 | 3864 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |