| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 | 145 |
| 146 // Probe the secondary table. | 146 // Probe the secondary table. |
| 147 ProbeTable(masm, flags, kSecondary, name, scratch, extra); | 147 ProbeTable(masm, flags, kSecondary, name, scratch, extra); |
| 148 | 148 |
| 149 // Cache miss: Fall-through and let caller handle the miss by | 149 // Cache miss: Fall-through and let caller handle the miss by |
| 150 // entering the runtime system. | 150 // entering the runtime system. |
| 151 __ bind(&miss); | 151 __ bind(&miss); |
| 152 } | 152 } |
| 153 | 153 |
| 154 | 154 |
| 155 static void PushInterceptorArguments(MacroAssembler* masm, | |
| 156 Register receiver, | |
| 157 Register holder, | |
| 158 Register name, | |
| 159 JSObject* holder_obj) { | |
| 160 __ push(receiver); | |
| 161 __ push(holder); | |
| 162 __ push(name); | |
| 163 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); | |
| 164 ASSERT(!Heap::InNewSpace(interceptor)); | |
| 165 __ mov(receiver, Immediate(Handle<Object>(interceptor))); | |
| 166 __ push(receiver); | |
| 167 __ push(FieldOperand(receiver, InterceptorInfo::kDataOffset)); | |
| 168 } | |
| 169 | |
| 170 | |
| 171 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, | 155 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, |
| 172 int index, | 156 int index, |
| 173 Register prototype) { | 157 Register prototype) { |
| 174 // Load the global or builtins object from the current context. | 158 // Load the global or builtins object from the current context. |
| 175 __ mov(prototype, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); | 159 __ mov(prototype, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 176 // Load the global context from the global or builtins object. | 160 // Load the global context from the global or builtins object. |
| 177 __ mov(prototype, | 161 __ mov(prototype, |
| 178 FieldOperand(prototype, GlobalObject::kGlobalContextOffset)); | 162 FieldOperand(prototype, GlobalObject::kGlobalContextOffset)); |
| 179 // Load the function from the global context. | 163 // Load the function from the global context. |
| 180 __ mov(prototype, Operand(prototype, Context::SlotOffset(index))); | 164 __ mov(prototype, Operand(prototype, Context::SlotOffset(index))); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); | 203 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 220 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | 204 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); |
| 221 ASSERT(kNotStringTag != 0); | 205 ASSERT(kNotStringTag != 0); |
| 222 __ test(scratch, Immediate(kNotStringTag)); | 206 __ test(scratch, Immediate(kNotStringTag)); |
| 223 __ j(not_zero, non_string_object, not_taken); | 207 __ j(not_zero, non_string_object, not_taken); |
| 224 } | 208 } |
| 225 | 209 |
| 226 | 210 |
| 227 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, | 211 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, |
| 228 Register receiver, | 212 Register receiver, |
| 229 Register scratch, | 213 Register scratch1, |
| 214 Register scratch2, |
| 230 Label* miss) { | 215 Label* miss) { |
| 231 Label load_length, check_wrapper; | 216 Label check_wrapper; |
| 232 | 217 |
| 233 // Check if the object is a string leaving the instance type in the | 218 // Check if the object is a string leaving the instance type in the |
| 234 // scratch register. | 219 // scratch register. |
| 235 GenerateStringCheck(masm, receiver, scratch, miss, &check_wrapper); | 220 GenerateStringCheck(masm, receiver, scratch1, miss, &check_wrapper); |
| 236 | 221 |
| 237 // Load length from the string and convert to a smi. | 222 // Load length from the string and convert to a smi. |
| 238 __ bind(&load_length); | |
| 239 __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); | 223 __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); |
| 240 __ SmiTag(eax); | 224 __ SmiTag(eax); |
| 241 __ ret(0); | 225 __ ret(0); |
| 242 | 226 |
| 243 // Check if the object is a JSValue wrapper. | 227 // Check if the object is a JSValue wrapper. |
| 244 __ bind(&check_wrapper); | 228 __ bind(&check_wrapper); |
| 245 __ cmp(scratch, JS_VALUE_TYPE); | 229 __ cmp(scratch1, JS_VALUE_TYPE); |
| 246 __ j(not_equal, miss, not_taken); | 230 __ j(not_equal, miss, not_taken); |
| 247 | 231 |
| 248 // Check if the wrapped value is a string and load the length | 232 // Check if the wrapped value is a string and load the length |
| 249 // directly if it is. | 233 // directly if it is. |
| 250 __ mov(receiver, FieldOperand(receiver, JSValue::kValueOffset)); | 234 __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); |
| 251 GenerateStringCheck(masm, receiver, scratch, miss, miss); | 235 GenerateStringCheck(masm, scratch2, scratch1, miss, miss); |
| 252 __ jmp(&load_length); | 236 __ mov(eax, FieldOperand(scratch2, String::kLengthOffset)); |
| 237 __ SmiTag(eax); |
| 238 __ ret(0); |
| 253 } | 239 } |
| 254 | 240 |
| 255 | 241 |
| 256 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, | 242 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, |
| 257 Register receiver, | 243 Register receiver, |
| 258 Register scratch1, | 244 Register scratch1, |
| 259 Register scratch2, | 245 Register scratch2, |
| 260 Label* miss_label) { | 246 Label* miss_label) { |
| 261 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); | 247 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); |
| 262 __ mov(eax, Operand(scratch1)); | 248 __ mov(eax, Operand(scratch1)); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 278 __ mov(dst, FieldOperand(src, offset)); | 264 __ mov(dst, FieldOperand(src, offset)); |
| 279 } else { | 265 } else { |
| 280 // Calculate the offset into the properties array. | 266 // Calculate the offset into the properties array. |
| 281 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 267 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
| 282 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); | 268 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); |
| 283 __ mov(dst, FieldOperand(dst, offset)); | 269 __ mov(dst, FieldOperand(dst, offset)); |
| 284 } | 270 } |
| 285 } | 271 } |
| 286 | 272 |
| 287 | 273 |
| 274 static void PushInterceptorArguments(MacroAssembler* masm, |
| 275 Register receiver, |
| 276 Register holder, |
| 277 Register name, |
| 278 JSObject* holder_obj) { |
| 279 __ push(receiver); |
| 280 __ push(holder); |
| 281 __ push(name); |
| 282 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); |
| 283 ASSERT(!Heap::InNewSpace(interceptor)); |
| 284 __ mov(receiver, Immediate(Handle<Object>(interceptor))); |
| 285 __ push(receiver); |
| 286 __ push(FieldOperand(receiver, InterceptorInfo::kDataOffset)); |
| 287 } |
| 288 |
| 289 |
| 288 static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, | 290 static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, |
| 289 Register receiver, | 291 Register receiver, |
| 290 Register holder, | 292 Register holder, |
| 291 Register name, | 293 Register name, |
| 292 JSObject* holder_obj) { | 294 JSObject* holder_obj) { |
| 293 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 295 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
| 294 | 296 __ CallExternalReference( |
| 295 ExternalReference ref = | 297 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)), |
| 296 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)); | 298 5); |
| 297 __ mov(eax, Immediate(5)); | |
| 298 __ mov(ebx, Immediate(ref)); | |
| 299 | |
| 300 CEntryStub stub(1); | |
| 301 __ CallStub(&stub); | |
| 302 } | 299 } |
| 303 | 300 |
| 304 | 301 |
| 305 template <class Compiler> | 302 template <class Compiler> |
| 306 static void CompileLoadInterceptor(Compiler* compiler, | 303 static void CompileLoadInterceptor(Compiler* compiler, |
| 307 StubCompiler* stub_compiler, | 304 StubCompiler* stub_compiler, |
| 308 MacroAssembler* masm, | 305 MacroAssembler* masm, |
| 309 JSObject* object, | 306 JSObject* object, |
| 310 JSObject* holder, | 307 JSObject* holder, |
| 311 String* name, | 308 String* name, |
| 312 LookupResult* lookup, | 309 LookupResult* lookup, |
| 313 Register receiver, | 310 Register receiver, |
| 314 Register scratch1, | 311 Register scratch1, |
| 315 Register scratch2, | 312 Register scratch2, |
| 316 Label* miss) { | 313 Label* miss) { |
| 317 ASSERT(holder->HasNamedInterceptor()); | 314 ASSERT(holder->HasNamedInterceptor()); |
| 318 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 315 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 319 | 316 |
| 320 // Check that the receiver isn't a smi. | 317 // Check that the receiver isn't a smi. |
| 321 __ test(receiver, Immediate(kSmiTagMask)); | 318 __ test(receiver, Immediate(kSmiTagMask)); |
| 322 __ j(zero, miss, not_taken); | 319 __ j(zero, miss, not_taken); |
| 323 | 320 |
| 324 // Check that the maps haven't changed. | 321 // Check that the maps haven't changed. |
| 325 Register reg = | 322 Register reg = |
| 326 stub_compiler->CheckPrototypes(object, receiver, holder, | 323 stub_compiler->CheckPrototypes(object, receiver, holder, |
| 327 scratch1, scratch2, name, miss); | 324 scratch1, scratch2, name, miss); |
| 328 | 325 |
| 329 if (lookup->IsValid() && lookup->IsCacheable()) { | 326 if (lookup->IsProperty() && lookup->IsCacheable()) { |
| 330 compiler->CompileCacheable(masm, | 327 compiler->CompileCacheable(masm, |
| 331 stub_compiler, | 328 stub_compiler, |
| 332 receiver, | 329 receiver, |
| 333 reg, | 330 reg, |
| 334 scratch1, | 331 scratch1, |
| 335 scratch2, | 332 scratch2, |
| 336 holder, | 333 holder, |
| 337 lookup, | 334 lookup, |
| 338 name, | 335 name, |
| 339 miss); | 336 miss); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 355 void CompileCacheable(MacroAssembler* masm, | 352 void CompileCacheable(MacroAssembler* masm, |
| 356 StubCompiler* stub_compiler, | 353 StubCompiler* stub_compiler, |
| 357 Register receiver, | 354 Register receiver, |
| 358 Register holder, | 355 Register holder, |
| 359 Register scratch1, | 356 Register scratch1, |
| 360 Register scratch2, | 357 Register scratch2, |
| 361 JSObject* holder_obj, | 358 JSObject* holder_obj, |
| 362 LookupResult* lookup, | 359 LookupResult* lookup, |
| 363 String* name, | 360 String* name, |
| 364 Label* miss_label) { | 361 Label* miss_label) { |
| 365 AccessorInfo* callback = 0; | 362 AccessorInfo* callback = NULL; |
| 366 bool optimize = false; | 363 bool optimize = false; |
| 367 // So far the most popular follow ups for interceptor loads are FIELD | 364 // So far the most popular follow ups for interceptor loads are FIELD |
| 368 // and CALLBACKS, so inline only them, other cases may be added | 365 // and CALLBACKS, so inline only them, other cases may be added |
| 369 // later. | 366 // later. |
| 370 if (lookup->type() == FIELD) { | 367 if (lookup->type() == FIELD) { |
| 371 optimize = true; | 368 optimize = true; |
| 372 } else if (lookup->type() == CALLBACKS) { | 369 } else if (lookup->type() == CALLBACKS) { |
| 373 Object* callback_object = lookup->GetCallbackObject(); | 370 Object* callback_object = lookup->GetCallbackObject(); |
| 374 if (callback_object->IsAccessorInfo()) { | 371 if (callback_object->IsAccessorInfo()) { |
| 375 callback = AccessorInfo::cast(callback_object); | 372 callback = AccessorInfo::cast(callback_object); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 472 ExternalReference ref = ExternalReference( | 469 ExternalReference ref = ExternalReference( |
| 473 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad)); | 470 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad)); |
| 474 __ TailCallRuntime(ref, 5, 1); | 471 __ TailCallRuntime(ref, 5, 1); |
| 475 } | 472 } |
| 476 | 473 |
| 477 private: | 474 private: |
| 478 Register name_; | 475 Register name_; |
| 479 }; | 476 }; |
| 480 | 477 |
| 481 | 478 |
| 479 // Holds information about possible function call optimizations. |
| 480 class CallOptimization BASE_EMBEDDED { |
| 481 public: |
| 482 explicit CallOptimization(LookupResult* lookup) |
| 483 : constant_function_(NULL), |
| 484 is_simple_api_call_(false), |
| 485 expected_receiver_type_(NULL), |
| 486 api_call_info_(NULL) { |
| 487 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; |
| 488 |
| 489 // We only optimize constant function calls. |
| 490 if (lookup->type() != CONSTANT_FUNCTION) return; |
| 491 |
| 492 Initialize(lookup->GetConstantFunction()); |
| 493 } |
| 494 |
| 495 explicit CallOptimization(JSFunction* function) { |
| 496 Initialize(function); |
| 497 } |
| 498 |
| 499 bool is_constant_call() const { |
| 500 return constant_function_ != NULL; |
| 501 } |
| 502 |
| 503 JSFunction* constant_function() const { |
| 504 ASSERT(constant_function_ != NULL); |
| 505 return constant_function_; |
| 506 } |
| 507 |
| 508 bool is_simple_api_call() const { |
| 509 return is_simple_api_call_; |
| 510 } |
| 511 |
| 512 FunctionTemplateInfo* expected_receiver_type() const { |
| 513 ASSERT(is_simple_api_call_); |
| 514 return expected_receiver_type_; |
| 515 } |
| 516 |
| 517 CallHandlerInfo* api_call_info() const { |
| 518 ASSERT(is_simple_api_call_); |
| 519 return api_call_info_; |
| 520 } |
| 521 |
| 522 // Returns the depth of the object having the expected type in the |
| 523 // prototype chain between the two arguments. |
| 524 int GetPrototypeDepthOfExpectedType(JSObject* object, |
| 525 JSObject* holder) const { |
| 526 ASSERT(is_simple_api_call_); |
| 527 if (expected_receiver_type_ == NULL) return 0; |
| 528 int depth = 0; |
| 529 while (object != holder) { |
| 530 if (object->IsInstanceOf(expected_receiver_type_)) return depth; |
| 531 object = JSObject::cast(object->GetPrototype()); |
| 532 ++depth; |
| 533 } |
| 534 if (holder->IsInstanceOf(expected_receiver_type_)) return depth; |
| 535 return kInvalidProtoDepth; |
| 536 } |
| 537 |
| 538 private: |
| 539 void Initialize(JSFunction* function) { |
| 540 if (!function->is_compiled()) return; |
| 541 |
| 542 constant_function_ = function; |
| 543 is_simple_api_call_ = false; |
| 544 |
| 545 AnalyzePossibleApiFunction(function); |
| 546 } |
| 547 |
| 548 // Determines whether the given function can be called using the |
| 549 // fast api call builtin. |
| 550 void AnalyzePossibleApiFunction(JSFunction* function) { |
| 551 SharedFunctionInfo* sfi = function->shared(); |
| 552 if (sfi->function_data()->IsUndefined()) return; |
| 553 FunctionTemplateInfo* info = |
| 554 FunctionTemplateInfo::cast(sfi->function_data()); |
| 555 |
| 556 // Require a C++ callback. |
| 557 if (info->call_code()->IsUndefined()) return; |
| 558 api_call_info_ = CallHandlerInfo::cast(info->call_code()); |
| 559 |
| 560 // Accept signatures that either have no restrictions at all or |
| 561 // only have restrictions on the receiver. |
| 562 if (!info->signature()->IsUndefined()) { |
| 563 SignatureInfo* signature = SignatureInfo::cast(info->signature()); |
| 564 if (!signature->args()->IsUndefined()) return; |
| 565 if (!signature->receiver()->IsUndefined()) { |
| 566 expected_receiver_type_ = |
| 567 FunctionTemplateInfo::cast(signature->receiver()); |
| 568 } |
| 569 } |
| 570 |
| 571 is_simple_api_call_ = true; |
| 572 } |
| 573 |
| 574 JSFunction* constant_function_; |
| 575 bool is_simple_api_call_; |
| 576 FunctionTemplateInfo* expected_receiver_type_; |
| 577 CallHandlerInfo* api_call_info_; |
| 578 }; |
| 579 |
| 580 |
| 581 // Reserves space for the extra arguments to FastHandleApiCall in the |
| 582 // caller's frame. |
| 583 // |
| 584 // These arguments are set by CheckPrototypes and GenerateFastApiCall. |
| 585 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { |
| 586 // ----------- S t a t e ------------- |
| 587 // -- esp[0] : return address |
| 588 // -- esp[4] : last argument in the internal frame of the caller |
| 589 // ----------------------------------- |
| 590 __ pop(scratch); |
| 591 __ push(Immediate(Smi::FromInt(0))); |
| 592 __ push(Immediate(Smi::FromInt(0))); |
| 593 __ push(Immediate(Smi::FromInt(0))); |
| 594 __ push(Immediate(Smi::FromInt(0))); |
| 595 __ push(scratch); |
| 596 } |
| 597 |
| 598 |
| 599 // Undoes the effects of ReserveSpaceForFastApiCall. |
| 600 static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { |
| 601 // ----------- S t a t e ------------- |
| 602 // -- esp[0] : return address |
| 603 // -- esp[4] : last fast api call extra argument |
| 604 // -- ... |
| 605 // -- esp[16] : first fast api call extra argument |
| 606 // -- esp[20] : last argument in the internal frame |
| 607 // ----------------------------------- |
| 608 __ pop(scratch); |
| 609 __ add(Operand(esp), Immediate(kPointerSize * 4)); |
| 610 __ push(scratch); |
| 611 } |
| 612 |
| 613 |
| 614 // Generates call to FastHandleApiCall builtin. |
| 615 static void GenerateFastApiCall(MacroAssembler* masm, |
| 616 const CallOptimization& optimization, |
| 617 int argc) { |
| 618 // ----------- S t a t e ------------- |
| 619 // -- esp[0] : return address |
| 620 // -- esp[4] : object passing the type check |
| 621 // (last fast api call extra argument, |
| 622 // set by CheckPrototypes) |
| 623 // -- esp[8] : api call data |
| 624 // -- esp[12] : api callback |
| 625 // -- esp[16] : api function |
| 626 // (first fast api call extra argument) |
| 627 // -- esp[20] : last argument |
| 628 // -- ... |
| 629 // -- esp[(argc + 5) * 4] : first argument |
| 630 // -- esp[(argc + 6) * 4] : receiver |
| 631 // ----------------------------------- |
| 632 |
| 633 // Get the function and setup the context. |
| 634 JSFunction* function = optimization.constant_function(); |
| 635 __ mov(edi, Immediate(Handle<JSFunction>(function))); |
| 636 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
| 637 |
| 638 // Pass the additional arguments FastHandleApiCall expects. |
| 639 __ mov(Operand(esp, 4 * kPointerSize), edi); |
| 640 bool info_loaded = false; |
| 641 Object* callback = optimization.api_call_info()->callback(); |
| 642 if (Heap::InNewSpace(callback)) { |
| 643 info_loaded = true; |
| 644 __ mov(ecx, Handle<CallHandlerInfo>(optimization.api_call_info())); |
| 645 __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kCallbackOffset)); |
| 646 __ mov(Operand(esp, 3 * kPointerSize), ebx); |
| 647 } else { |
| 648 __ mov(Operand(esp, 3 * kPointerSize), Immediate(Handle<Object>(callback))); |
| 649 } |
| 650 Object* call_data = optimization.api_call_info()->data(); |
| 651 if (Heap::InNewSpace(call_data)) { |
| 652 if (!info_loaded) { |
| 653 __ mov(ecx, Handle<CallHandlerInfo>(optimization.api_call_info())); |
| 654 } |
| 655 __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset)); |
| 656 __ mov(Operand(esp, 2 * kPointerSize), ebx); |
| 657 } else { |
| 658 __ mov(Operand(esp, 2 * kPointerSize), |
| 659 Immediate(Handle<Object>(call_data))); |
| 660 } |
| 661 |
| 662 // Set the number of arguments. |
| 663 __ mov(eax, Immediate(argc + 4)); |
| 664 |
| 665 // Jump to the fast api call builtin (tail call). |
| 666 Handle<Code> code = Handle<Code>( |
| 667 Builtins::builtin(Builtins::FastHandleApiCall)); |
| 668 ParameterCount expected(0); |
| 669 __ InvokeCode(code, expected, expected, |
| 670 RelocInfo::CODE_TARGET, JUMP_FUNCTION); |
| 671 } |
| 672 |
| 673 |
| 482 class CallInterceptorCompiler BASE_EMBEDDED { | 674 class CallInterceptorCompiler BASE_EMBEDDED { |
| 483 public: | 675 public: |
| 484 CallInterceptorCompiler(const ParameterCount& arguments, Register name) | 676 CallInterceptorCompiler(StubCompiler* stub_compiler, |
| 485 : arguments_(arguments), argc_(arguments.immediate()), name_(name) {} | 677 const ParameterCount& arguments, |
| 486 | 678 Register name) |
| 679 : stub_compiler_(stub_compiler), |
| 680 arguments_(arguments), |
| 681 name_(name) {} |
| 682 |
| 683 void Compile(MacroAssembler* masm, |
| 684 JSObject* object, |
| 685 JSObject* holder, |
| 686 String* name, |
| 687 LookupResult* lookup, |
| 688 Register receiver, |
| 689 Register scratch1, |
| 690 Register scratch2, |
| 691 Label* miss) { |
| 692 ASSERT(holder->HasNamedInterceptor()); |
| 693 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 694 |
| 695 // Check that the receiver isn't a smi. |
| 696 __ test(receiver, Immediate(kSmiTagMask)); |
| 697 __ j(zero, miss, not_taken); |
| 698 |
| 699 CallOptimization optimization(lookup); |
| 700 |
| 701 if (optimization.is_constant_call() && |
| 702 !Top::CanHaveSpecialFunctions(holder)) { |
| 703 CompileCacheable(masm, |
| 704 object, |
| 705 receiver, |
| 706 scratch1, |
| 707 scratch2, |
| 708 holder, |
| 709 lookup, |
| 710 name, |
| 711 optimization, |
| 712 miss); |
| 713 } else { |
| 714 CompileRegular(masm, |
| 715 object, |
| 716 receiver, |
| 717 scratch1, |
| 718 scratch2, |
| 719 name, |
| 720 holder, |
| 721 miss); |
| 722 } |
| 723 } |
| 724 |
| 725 private: |
| 487 void CompileCacheable(MacroAssembler* masm, | 726 void CompileCacheable(MacroAssembler* masm, |
| 488 StubCompiler* stub_compiler, | 727 JSObject* object, |
| 489 Register receiver, | 728 Register receiver, |
| 490 Register holder, | |
| 491 Register scratch1, | 729 Register scratch1, |
| 492 Register scratch2, | 730 Register scratch2, |
| 493 JSObject* holder_obj, | 731 JSObject* holder_obj, |
| 494 LookupResult* lookup, | 732 LookupResult* lookup, |
| 495 String* name, | 733 String* name, |
| 734 const CallOptimization& optimization, |
| 496 Label* miss_label) { | 735 Label* miss_label) { |
| 497 JSFunction* function = 0; | 736 ASSERT(optimization.is_constant_call()); |
| 498 bool optimize = false; | 737 ASSERT(!lookup->holder()->IsGlobalObject()); |
| 499 // So far the most popular case for failed interceptor is | 738 |
| 500 // CONSTANT_FUNCTION sitting below. | 739 int depth1 = kInvalidProtoDepth; |
| 501 if (lookup->type() == CONSTANT_FUNCTION) { | 740 int depth2 = kInvalidProtoDepth; |
| 502 function = lookup->GetConstantFunction(); | 741 bool can_do_fast_api_call = false; |
| 503 // JSArray holder is a special case for call constant function | 742 if (optimization.is_simple_api_call() && |
| 504 // (see the corresponding code). | 743 !lookup->holder()->IsGlobalObject()) { |
| 505 if (function->is_compiled() && !holder_obj->IsJSArray()) { | 744 depth1 = optimization.GetPrototypeDepthOfExpectedType(object, holder_obj); |
| 506 optimize = true; | 745 if (depth1 == kInvalidProtoDepth) { |
| 746 depth2 = optimization.GetPrototypeDepthOfExpectedType(holder_obj, |
| 747 lookup->holder()); |
| 507 } | 748 } |
| 508 } | 749 can_do_fast_api_call = (depth1 != kInvalidProtoDepth) || |
| 509 | 750 (depth2 != kInvalidProtoDepth); |
| 510 if (!optimize) { | 751 } |
| 511 CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label); | 752 |
| 512 return; | 753 __ IncrementCounter(&Counters::call_const_interceptor, 1); |
| 513 } | 754 |
| 514 | 755 if (can_do_fast_api_call) { |
| 515 __ EnterInternalFrame(); | 756 __ IncrementCounter(&Counters::call_const_interceptor_fast_api, 1); |
| 516 __ push(holder); // Save the holder. | 757 ReserveSpaceForFastApiCall(masm, scratch1); |
| 517 __ push(name_); // Save the name. | 758 } |
| 518 | 759 |
| 519 CompileCallLoadPropertyWithInterceptor(masm, | 760 Label miss_cleanup; |
| 520 receiver, | 761 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; |
| 521 holder, | 762 Register holder = |
| 522 name_, | 763 stub_compiler_->CheckPrototypes(object, receiver, holder_obj, |
| 523 holder_obj); | 764 scratch1, scratch2, name, |
| 524 | 765 depth1, miss); |
| 525 __ pop(name_); // Restore the name. | 766 |
| 526 __ pop(receiver); // Restore the holder. | 767 Label regular_invoke; |
| 527 __ LeaveInternalFrame(); | 768 LoadWithInterceptor(masm, receiver, holder, holder_obj, ®ular_invoke); |
| 528 | 769 |
| 529 __ cmp(eax, Factory::no_interceptor_result_sentinel()); | 770 // Generate code for the failed interceptor case. |
| 530 Label invoke; | 771 |
| 531 __ j(not_equal, &invoke); | 772 // Check the lookup is still valid. |
| 532 | 773 stub_compiler_->CheckPrototypes(holder_obj, receiver, |
| 533 stub_compiler->CheckPrototypes(holder_obj, receiver, | 774 lookup->holder(), |
| 534 lookup->holder(), scratch1, | 775 scratch1, scratch2, name, |
| 535 scratch2, | 776 depth2, miss); |
| 536 name, | 777 |
| 537 miss_label); | 778 if (can_do_fast_api_call) { |
| 538 if (lookup->holder()->IsGlobalObject()) { | 779 GenerateFastApiCall(masm, optimization, arguments_.immediate()); |
| 539 __ mov(edx, Operand(esp, (argc_ + 1) * kPointerSize)); | 780 } else { |
| 540 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 781 __ InvokeFunction(optimization.constant_function(), arguments_, |
| 541 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), edx); | 782 JUMP_FUNCTION); |
| 542 } | 783 } |
| 543 | 784 |
| 544 ASSERT(function->is_compiled()); | 785 if (can_do_fast_api_call) { |
| 545 // Get the function and setup the context. | 786 __ bind(&miss_cleanup); |
| 546 __ mov(edi, Immediate(Handle<JSFunction>(function))); | 787 FreeSpaceForFastApiCall(masm, scratch1); |
| 547 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 788 __ jmp(miss_label); |
| 548 | 789 } |
| 549 // Jump to the cached code (tail call). | 790 |
| 550 Handle<Code> code(function->code()); | 791 __ bind(®ular_invoke); |
| 551 ParameterCount expected(function->shared()->formal_parameter_count()); | 792 if (can_do_fast_api_call) { |
| 552 __ InvokeCode(code, expected, arguments_, | 793 FreeSpaceForFastApiCall(masm, scratch1); |
| 553 RelocInfo::CODE_TARGET, JUMP_FUNCTION); | 794 } |
| 554 | |
| 555 __ bind(&invoke); | |
| 556 } | 795 } |
| 557 | 796 |
| 558 void CompileRegular(MacroAssembler* masm, | 797 void CompileRegular(MacroAssembler* masm, |
| 798 JSObject* object, |
| 559 Register receiver, | 799 Register receiver, |
| 560 Register holder, | 800 Register scratch1, |
| 561 Register scratch, | 801 Register scratch2, |
| 802 String* name, |
| 562 JSObject* holder_obj, | 803 JSObject* holder_obj, |
| 563 Label* miss_label) { | 804 Label* miss_label) { |
| 805 Register holder = |
| 806 stub_compiler_->CheckPrototypes(object, receiver, holder_obj, |
| 807 scratch1, scratch2, name, |
| 808 miss_label); |
| 809 |
| 564 __ EnterInternalFrame(); | 810 __ EnterInternalFrame(); |
| 565 // Save the name_ register across the call. | 811 // Save the name_ register across the call. |
| 566 __ push(name_); | 812 __ push(name_); |
| 567 | 813 |
| 568 PushInterceptorArguments(masm, | 814 PushInterceptorArguments(masm, |
| 569 receiver, | 815 receiver, |
| 570 holder, | 816 holder, |
| 571 name_, | 817 name_, |
| 572 holder_obj); | 818 holder_obj); |
| 573 | 819 |
| 574 ExternalReference ref = ExternalReference( | 820 __ CallExternalReference( |
| 575 IC_Utility(IC::kLoadPropertyWithInterceptorForCall)); | 821 ExternalReference( |
| 576 __ mov(eax, Immediate(5)); | 822 IC_Utility(IC::kLoadPropertyWithInterceptorForCall)), |
| 577 __ mov(ebx, Immediate(ref)); | 823 5); |
| 578 | |
| 579 CEntryStub stub(1); | |
| 580 __ CallStub(&stub); | |
| 581 | 824 |
| 582 // Restore the name_ register. | 825 // Restore the name_ register. |
| 583 __ pop(name_); | 826 __ pop(name_); |
| 584 __ LeaveInternalFrame(); | 827 __ LeaveInternalFrame(); |
| 585 } | 828 } |
| 586 | 829 |
| 587 private: | 830 void LoadWithInterceptor(MacroAssembler* masm, |
| 831 Register receiver, |
| 832 Register holder, |
| 833 JSObject* holder_obj, |
| 834 Label* interceptor_succeeded) { |
| 835 __ EnterInternalFrame(); |
| 836 __ push(holder); // Save the holder. |
| 837 __ push(name_); // Save the name. |
| 838 |
| 839 CompileCallLoadPropertyWithInterceptor(masm, |
| 840 receiver, |
| 841 holder, |
| 842 name_, |
| 843 holder_obj); |
| 844 |
| 845 __ pop(name_); // Restore the name. |
| 846 __ pop(receiver); // Restore the holder. |
| 847 __ LeaveInternalFrame(); |
| 848 |
| 849 __ cmp(eax, Factory::no_interceptor_result_sentinel()); |
| 850 __ j(not_equal, interceptor_succeeded); |
| 851 } |
| 852 |
| 853 StubCompiler* stub_compiler_; |
| 588 const ParameterCount& arguments_; | 854 const ParameterCount& arguments_; |
| 589 int argc_; | |
| 590 Register name_; | 855 Register name_; |
| 591 }; | 856 }; |
| 592 | 857 |
| 593 | 858 |
| 594 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { | 859 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { |
| 595 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); | 860 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); |
| 596 Code* code = NULL; | 861 Code* code = NULL; |
| 597 if (kind == Code::LOAD_IC) { | 862 if (kind == Code::LOAD_IC) { |
| 598 code = Builtins::builtin(Builtins::LoadIC_Miss); | 863 code = Builtins::builtin(Builtins::LoadIC_Miss); |
| 599 } else { | 864 } else { |
| 600 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss); | 865 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss); |
| 601 } | 866 } |
| 602 | 867 |
| 603 Handle<Code> ic(code); | 868 Handle<Code> ic(code); |
| 604 __ jmp(ic, RelocInfo::CODE_TARGET); | 869 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 605 } | 870 } |
| 606 | 871 |
| 607 | 872 |
| 873 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
| 874 // but may be destroyed if store is successful. |
| 608 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 875 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
| 609 Builtins::Name storage_extend, | |
| 610 JSObject* object, | 876 JSObject* object, |
| 611 int index, | 877 int index, |
| 612 Map* transition, | 878 Map* transition, |
| 613 Register receiver_reg, | 879 Register receiver_reg, |
| 614 Register name_reg, | 880 Register name_reg, |
| 615 Register scratch, | 881 Register scratch, |
| 616 Label* miss_label) { | 882 Label* miss_label) { |
| 617 // Check that the object isn't a smi. | 883 // Check that the object isn't a smi. |
| 618 __ test(receiver_reg, Immediate(kSmiTagMask)); | 884 __ test(receiver_reg, Immediate(kSmiTagMask)); |
| 619 __ j(zero, miss_label, not_taken); | 885 __ j(zero, miss_label, not_taken); |
| 620 | 886 |
| 621 // Check that the map of the object hasn't changed. | 887 // Check that the map of the object hasn't changed. |
| 622 __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), | 888 __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), |
| 623 Immediate(Handle<Map>(object->map()))); | 889 Immediate(Handle<Map>(object->map()))); |
| 624 __ j(not_equal, miss_label, not_taken); | 890 __ j(not_equal, miss_label, not_taken); |
| 625 | 891 |
| 626 // Perform global security token check if needed. | 892 // Perform global security token check if needed. |
| 627 if (object->IsJSGlobalProxy()) { | 893 if (object->IsJSGlobalProxy()) { |
| 628 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); | 894 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); |
| 629 } | 895 } |
| 630 | 896 |
| 631 // Stub never generated for non-global objects that require access | 897 // Stub never generated for non-global objects that require access |
| 632 // checks. | 898 // checks. |
| 633 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 899 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 634 | 900 |
| 635 // Perform map transition for the receiver if necessary. | 901 // Perform map transition for the receiver if necessary. |
| 636 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) { | 902 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) { |
| 637 // The properties must be extended before we can store the value. | 903 // The properties must be extended before we can store the value. |
| 638 // We jump to a runtime call that extends the properties array. | 904 // We jump to a runtime call that extends the properties array. |
| 639 __ mov(ecx, Immediate(Handle<Map>(transition))); | 905 __ pop(scratch); // Return address. |
| 640 Handle<Code> ic(Builtins::builtin(storage_extend)); | 906 __ push(receiver_reg); |
| 641 __ jmp(ic, RelocInfo::CODE_TARGET); | 907 __ push(Immediate(Handle<Map>(transition))); |
| 908 __ push(eax); |
| 909 __ push(scratch); |
| 910 __ TailCallRuntime( |
| 911 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage)), 3, 1); |
| 642 return; | 912 return; |
| 643 } | 913 } |
| 644 | 914 |
| 645 if (transition != NULL) { | 915 if (transition != NULL) { |
| 646 // Update the map of the object; no write barrier updating is | 916 // Update the map of the object; no write barrier updating is |
| 647 // needed because the map is never in new space. | 917 // needed because the map is never in new space. |
| 648 __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset), | 918 __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset), |
| 649 Immediate(Handle<Map>(transition))); | 919 Immediate(Handle<Map>(transition))); |
| 650 } | 920 } |
| 651 | 921 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 684 #undef __ | 954 #undef __ |
| 685 #define __ ACCESS_MASM(masm()) | 955 #define __ ACCESS_MASM(masm()) |
| 686 | 956 |
| 687 | 957 |
| 688 Register StubCompiler::CheckPrototypes(JSObject* object, | 958 Register StubCompiler::CheckPrototypes(JSObject* object, |
| 689 Register object_reg, | 959 Register object_reg, |
| 690 JSObject* holder, | 960 JSObject* holder, |
| 691 Register holder_reg, | 961 Register holder_reg, |
| 692 Register scratch, | 962 Register scratch, |
| 693 String* name, | 963 String* name, |
| 964 int push_at_depth, |
| 694 Label* miss) { | 965 Label* miss) { |
| 695 // Check that the maps haven't changed. | 966 // Check that the maps haven't changed. |
| 696 Register result = | 967 Register result = |
| 697 masm()->CheckMaps(object, object_reg, holder, holder_reg, scratch, miss); | 968 masm()->CheckMaps(object, object_reg, holder, holder_reg, scratch, |
| 969 push_at_depth, miss); |
| 698 | 970 |
| 699 // If we've skipped any global objects, it's not enough to verify | 971 // If we've skipped any global objects, it's not enough to verify |
| 700 // that their maps haven't changed. | 972 // that their maps haven't changed. |
| 701 while (object != holder) { | 973 while (object != holder) { |
| 702 if (object->IsGlobalObject()) { | 974 if (object->IsGlobalObject()) { |
| 703 GlobalObject* global = GlobalObject::cast(object); | 975 GlobalObject* global = GlobalObject::cast(object); |
| 704 Object* probe = global->EnsurePropertyCell(name); | 976 Object* probe = global->EnsurePropertyCell(name); |
| 705 if (probe->IsFailure()) { | 977 if (probe->IsFailure()) { |
| 706 set_failure(Failure::cast(probe)); | 978 set_failure(Failure::cast(probe)); |
| 707 return result; | 979 return result; |
| 708 } | 980 } |
| 709 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); | 981 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); |
| 710 ASSERT(cell->value()->IsTheHole()); | 982 ASSERT(cell->value()->IsTheHole()); |
| 711 __ mov(scratch, Immediate(Handle<Object>(cell))); | 983 __ mov(scratch, Immediate(Handle<Object>(cell))); |
| 712 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), | 984 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), |
| 713 Immediate(Factory::the_hole_value())); | 985 Immediate(Factory::the_hole_value())); |
| 714 __ j(not_equal, miss, not_taken); | 986 __ j(not_equal, miss, not_taken); |
| 715 } | 987 } |
| 716 object = JSObject::cast(object->GetPrototype()); | 988 object = JSObject::cast(object->GetPrototype()); |
| 717 } | 989 } |
| 718 | 990 |
| 719 // Return the register containin the holder. | 991 // Return the register containing the holder. |
| 720 return result; | 992 return result; |
| 721 } | 993 } |
| 722 | 994 |
| 723 | 995 |
| 724 void StubCompiler::GenerateLoadField(JSObject* object, | 996 void StubCompiler::GenerateLoadField(JSObject* object, |
| 725 JSObject* holder, | 997 JSObject* holder, |
| 726 Register receiver, | 998 Register receiver, |
| 727 Register scratch1, | 999 Register scratch1, |
| 728 Register scratch2, | 1000 Register scratch2, |
| 729 int index, | 1001 int index, |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 880 __ LeaveInternalFrame(); | 1152 __ LeaveInternalFrame(); |
| 881 | 1153 |
| 882 // Do a tail-call of the compiled function. | 1154 // Do a tail-call of the compiled function. |
| 883 __ lea(ecx, FieldOperand(eax, Code::kHeaderSize)); | 1155 __ lea(ecx, FieldOperand(eax, Code::kHeaderSize)); |
| 884 __ jmp(Operand(ecx)); | 1156 __ jmp(Operand(ecx)); |
| 885 | 1157 |
| 886 return GetCodeWithFlags(flags, "LazyCompileStub"); | 1158 return GetCodeWithFlags(flags, "LazyCompileStub"); |
| 887 } | 1159 } |
| 888 | 1160 |
| 889 | 1161 |
| 890 Object* CallStubCompiler::CompileCallField(Object* object, | 1162 Object* CallStubCompiler::CompileCallField(JSObject* object, |
| 891 JSObject* holder, | 1163 JSObject* holder, |
| 892 int index, | 1164 int index, |
| 893 String* name) { | 1165 String* name) { |
| 894 // ----------- S t a t e ------------- | 1166 // ----------- S t a t e ------------- |
| 895 // -- ecx : name | 1167 // -- ecx : name |
| 896 // -- esp[0] : return address | 1168 // -- esp[0] : return address |
| 897 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1169 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 898 // -- ... | 1170 // -- ... |
| 899 // -- esp[(argc + 1) * 4] : receiver | 1171 // -- esp[(argc + 1) * 4] : receiver |
| 900 // ----------------------------------- | 1172 // ----------------------------------- |
| 901 Label miss; | 1173 Label miss; |
| 902 | 1174 |
| 903 // Get the receiver from the stack. | 1175 // Get the receiver from the stack. |
| 904 const int argc = arguments().immediate(); | 1176 const int argc = arguments().immediate(); |
| 905 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1177 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 906 | 1178 |
| 907 // Check that the receiver isn't a smi. | 1179 // Check that the receiver isn't a smi. |
| 908 __ test(edx, Immediate(kSmiTagMask)); | 1180 __ test(edx, Immediate(kSmiTagMask)); |
| 909 __ j(zero, &miss, not_taken); | 1181 __ j(zero, &miss, not_taken); |
| 910 | 1182 |
| 911 // Do the right check and compute the holder register. | 1183 // Do the right check and compute the holder register. |
| 912 Register reg = | 1184 Register reg = CheckPrototypes(object, edx, holder, ebx, eax, name, &miss); |
| 913 CheckPrototypes(JSObject::cast(object), edx, holder, | |
| 914 ebx, eax, name, &miss); | |
| 915 | 1185 |
| 916 GenerateFastPropertyLoad(masm(), edi, reg, holder, index); | 1186 GenerateFastPropertyLoad(masm(), edi, reg, holder, index); |
| 917 | 1187 |
| 918 // Check that the function really is a function. | 1188 // Check that the function really is a function. |
| 919 __ test(edi, Immediate(kSmiTagMask)); | 1189 __ test(edi, Immediate(kSmiTagMask)); |
| 920 __ j(zero, &miss, not_taken); | 1190 __ j(zero, &miss, not_taken); |
| 921 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | 1191 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); |
| 922 __ j(not_equal, &miss, not_taken); | 1192 __ j(not_equal, &miss, not_taken); |
| 923 | 1193 |
| 924 // Patch the receiver on the stack with the global proxy if | 1194 // Patch the receiver on the stack with the global proxy if |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 962 // Check that the receiver isn't a smi. | 1232 // Check that the receiver isn't a smi. |
| 963 if (check != NUMBER_CHECK) { | 1233 if (check != NUMBER_CHECK) { |
| 964 __ test(edx, Immediate(kSmiTagMask)); | 1234 __ test(edx, Immediate(kSmiTagMask)); |
| 965 __ j(zero, &miss, not_taken); | 1235 __ j(zero, &miss, not_taken); |
| 966 } | 1236 } |
| 967 | 1237 |
| 968 // Make sure that it's okay not to patch the on stack receiver | 1238 // Make sure that it's okay not to patch the on stack receiver |
| 969 // unless we're doing a receiver map check. | 1239 // unless we're doing a receiver map check. |
| 970 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 1240 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 971 | 1241 |
| 1242 CallOptimization optimization(function); |
| 1243 int depth = kInvalidProtoDepth; |
| 1244 |
| 972 switch (check) { | 1245 switch (check) { |
| 973 case RECEIVER_MAP_CHECK: | 1246 case RECEIVER_MAP_CHECK: |
| 1247 __ IncrementCounter(&Counters::call_const, 1); |
| 1248 |
| 1249 if (optimization.is_simple_api_call() && !object->IsGlobalObject()) { |
| 1250 depth = optimization.GetPrototypeDepthOfExpectedType( |
| 1251 JSObject::cast(object), holder); |
| 1252 } |
| 1253 |
| 1254 if (depth != kInvalidProtoDepth) { |
| 1255 __ IncrementCounter(&Counters::call_const_fast_api, 1); |
| 1256 ReserveSpaceForFastApiCall(masm(), eax); |
| 1257 } |
| 1258 |
| 974 // Check that the maps haven't changed. | 1259 // Check that the maps haven't changed. |
| 975 CheckPrototypes(JSObject::cast(object), edx, holder, | 1260 CheckPrototypes(JSObject::cast(object), edx, holder, |
| 976 ebx, eax, name, &miss); | 1261 ebx, eax, name, depth, &miss); |
| 977 | 1262 |
| 978 // Patch the receiver on the stack with the global proxy if | 1263 // Patch the receiver on the stack with the global proxy if |
| 979 // necessary. | 1264 // necessary. |
| 980 if (object->IsGlobalObject()) { | 1265 if (object->IsGlobalObject()) { |
| 1266 ASSERT(depth == kInvalidProtoDepth); |
| 981 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 1267 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
| 982 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 1268 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
| 983 } | 1269 } |
| 984 break; | 1270 break; |
| 985 | 1271 |
| 986 case STRING_CHECK: | 1272 case STRING_CHECK: |
| 987 if (!function->IsBuiltin()) { | 1273 if (!function->IsBuiltin()) { |
| 988 // Calling non-builtins with a value as receiver requires boxing. | 1274 // Calling non-builtins with a value as receiver requires boxing. |
| 989 __ jmp(&miss); | 1275 __ jmp(&miss); |
| 990 } else { | 1276 } else { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1055 // Check that the object is in fast mode (not dictionary). | 1341 // Check that the object is in fast mode (not dictionary). |
| 1056 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), | 1342 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), |
| 1057 Immediate(Factory::fixed_array_map())); | 1343 Immediate(Factory::fixed_array_map())); |
| 1058 __ j(not_equal, &miss, not_taken); | 1344 __ j(not_equal, &miss, not_taken); |
| 1059 break; | 1345 break; |
| 1060 | 1346 |
| 1061 default: | 1347 default: |
| 1062 UNREACHABLE(); | 1348 UNREACHABLE(); |
| 1063 } | 1349 } |
| 1064 | 1350 |
| 1065 // Get the function and setup the context. | 1351 if (depth != kInvalidProtoDepth) { |
| 1066 __ mov(edi, Immediate(Handle<JSFunction>(function))); | 1352 GenerateFastApiCall(masm(), optimization, argc); |
| 1067 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 1353 } else { |
| 1068 | 1354 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); |
| 1069 // Jump to the cached code (tail call). | 1355 } |
| 1070 ASSERT(function->is_compiled()); | |
| 1071 Handle<Code> code(function->code()); | |
| 1072 ParameterCount expected(function->shared()->formal_parameter_count()); | |
| 1073 __ InvokeCode(code, expected, arguments(), | |
| 1074 RelocInfo::CODE_TARGET, JUMP_FUNCTION); | |
| 1075 | 1356 |
| 1076 // Handle call cache miss. | 1357 // Handle call cache miss. |
| 1077 __ bind(&miss); | 1358 __ bind(&miss); |
| 1359 if (depth != kInvalidProtoDepth) { |
| 1360 FreeSpaceForFastApiCall(masm(), eax); |
| 1361 } |
| 1078 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); | 1362 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); |
| 1079 __ jmp(ic, RelocInfo::CODE_TARGET); | 1363 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 1080 | 1364 |
| 1081 // Return the generated code. | 1365 // Return the generated code. |
| 1082 String* function_name = NULL; | 1366 String* function_name = NULL; |
| 1083 if (function->shared()->name()->IsString()) { | 1367 if (function->shared()->name()->IsString()) { |
| 1084 function_name = String::cast(function->shared()->name()); | 1368 function_name = String::cast(function->shared()->name()); |
| 1085 } | 1369 } |
| 1086 return GetCode(CONSTANT_FUNCTION, function_name); | 1370 return GetCode(CONSTANT_FUNCTION, function_name); |
| 1087 } | 1371 } |
| 1088 | 1372 |
| 1089 | 1373 |
| 1090 Object* CallStubCompiler::CompileCallInterceptor(Object* object, | 1374 Object* CallStubCompiler::CompileCallInterceptor(JSObject* object, |
| 1091 JSObject* holder, | 1375 JSObject* holder, |
| 1092 String* name) { | 1376 String* name) { |
| 1093 // ----------- S t a t e ------------- | 1377 // ----------- S t a t e ------------- |
| 1094 // -- ecx : name | 1378 // -- ecx : name |
| 1095 // -- esp[0] : return address | 1379 // -- esp[0] : return address |
| 1096 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1380 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1097 // -- ... | 1381 // -- ... |
| 1098 // -- esp[(argc + 1) * 4] : receiver | 1382 // -- esp[(argc + 1) * 4] : receiver |
| 1099 // ----------------------------------- | 1383 // ----------------------------------- |
| 1100 Label miss; | 1384 Label miss; |
| 1101 | 1385 |
| 1102 // Get the number of arguments. | 1386 // Get the number of arguments. |
| 1103 const int argc = arguments().immediate(); | 1387 const int argc = arguments().immediate(); |
| 1104 | 1388 |
| 1105 LookupResult lookup; | 1389 LookupResult lookup; |
| 1106 LookupPostInterceptor(holder, name, &lookup); | 1390 LookupPostInterceptor(holder, name, &lookup); |
| 1107 | 1391 |
| 1108 // Get the receiver from the stack. | 1392 // Get the receiver from the stack. |
| 1109 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1393 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1110 | 1394 |
| 1111 CallInterceptorCompiler compiler(arguments(), ecx); | 1395 CallInterceptorCompiler compiler(this, arguments(), ecx); |
| 1112 CompileLoadInterceptor(&compiler, | 1396 compiler.Compile(masm(), |
| 1113 this, | 1397 object, |
| 1114 masm(), | 1398 holder, |
| 1115 JSObject::cast(object), | 1399 name, |
| 1116 holder, | 1400 &lookup, |
| 1117 name, | 1401 edx, |
| 1118 &lookup, | 1402 ebx, |
| 1119 edx, | 1403 edi, |
| 1120 ebx, | 1404 &miss); |
| 1121 edi, | |
| 1122 &miss); | |
| 1123 | 1405 |
| 1124 // Restore receiver. | 1406 // Restore receiver. |
| 1125 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1407 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1126 | 1408 |
| 1127 // Check that the function really is a function. | 1409 // Check that the function really is a function. |
| 1128 __ test(eax, Immediate(kSmiTagMask)); | 1410 __ test(eax, Immediate(kSmiTagMask)); |
| 1129 __ j(zero, &miss, not_taken); | 1411 __ j(zero, &miss, not_taken); |
| 1130 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); | 1412 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); |
| 1131 __ j(not_equal, &miss, not_taken); | 1413 __ j(not_equal, &miss, not_taken); |
| 1132 | 1414 |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1242 // ----------- S t a t e ------------- | 1524 // ----------- S t a t e ------------- |
| 1243 // -- eax : value | 1525 // -- eax : value |
| 1244 // -- ecx : name | 1526 // -- ecx : name |
| 1245 // -- edx : receiver | 1527 // -- edx : receiver |
| 1246 // -- esp[0] : return address | 1528 // -- esp[0] : return address |
| 1247 // ----------------------------------- | 1529 // ----------------------------------- |
| 1248 Label miss; | 1530 Label miss; |
| 1249 | 1531 |
| 1250 // Generate store field code. Trashes the name register. | 1532 // Generate store field code. Trashes the name register. |
| 1251 GenerateStoreField(masm(), | 1533 GenerateStoreField(masm(), |
| 1252 Builtins::StoreIC_ExtendStorage, | |
| 1253 object, | 1534 object, |
| 1254 index, | 1535 index, |
| 1255 transition, | 1536 transition, |
| 1256 edx, ecx, ebx, | 1537 edx, ecx, ebx, |
| 1257 &miss); | 1538 &miss); |
| 1258 | 1539 |
| 1259 // Handle store cache miss. | 1540 // Handle store cache miss. |
| 1260 __ bind(&miss); | 1541 __ bind(&miss); |
| 1261 __ mov(ecx, Immediate(Handle<String>(name))); // restore name | 1542 __ mov(ecx, Immediate(Handle<String>(name))); // restore name |
| 1262 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); | 1543 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1416 | 1697 |
| 1417 __ IncrementCounter(&Counters::keyed_store_field, 1); | 1698 __ IncrementCounter(&Counters::keyed_store_field, 1); |
| 1418 | 1699 |
| 1419 // Get the name from the stack. | 1700 // Get the name from the stack. |
| 1420 __ mov(ecx, Operand(esp, 1 * kPointerSize)); | 1701 __ mov(ecx, Operand(esp, 1 * kPointerSize)); |
| 1421 // Check that the name has not changed. | 1702 // Check that the name has not changed. |
| 1422 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); | 1703 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); |
| 1423 __ j(not_equal, &miss, not_taken); | 1704 __ j(not_equal, &miss, not_taken); |
| 1424 | 1705 |
| 1425 // Get the object from the stack. | 1706 // Get the object from the stack. |
| 1426 __ mov(ebx, Operand(esp, 2 * kPointerSize)); | 1707 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
| 1427 | 1708 |
| 1428 // Generate store field code. Trashes the name register. | 1709 // Generate store field code. Trashes the name register. |
| 1429 GenerateStoreField(masm(), | 1710 GenerateStoreField(masm(), |
| 1430 Builtins::KeyedStoreIC_ExtendStorage, | |
| 1431 object, | 1711 object, |
| 1432 index, | 1712 index, |
| 1433 transition, | 1713 transition, |
| 1434 ebx, ecx, edx, | 1714 edx, ecx, ebx, |
| 1435 &miss); | 1715 &miss); |
| 1436 | 1716 |
| 1437 // Handle store cache miss. | 1717 // Handle store cache miss. |
| 1438 __ bind(&miss); | 1718 __ bind(&miss); |
| 1439 __ DecrementCounter(&Counters::keyed_store_field, 1); | 1719 __ DecrementCounter(&Counters::keyed_store_field, 1); |
| 1440 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss)); | 1720 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss)); |
| 1441 __ jmp(ic, RelocInfo::CODE_TARGET); | 1721 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 1442 | 1722 |
| 1443 // Return the generated code. | 1723 // Return the generated code. |
| 1444 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 1724 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); |
| 1445 } | 1725 } |
| 1446 | 1726 |
| 1447 | 1727 |
| 1448 | 1728 |
| 1449 Object* LoadStubCompiler::CompileLoadField(JSObject* object, | 1729 Object* LoadStubCompiler::CompileLoadField(JSObject* object, |
| 1450 JSObject* holder, | 1730 JSObject* holder, |
| 1451 int index, | 1731 int index, |
| 1452 String* name) { | 1732 String* name) { |
| 1453 // ----------- S t a t e ------------- | 1733 // ----------- S t a t e ------------- |
| 1734 // -- eax : receiver |
| 1454 // -- ecx : name | 1735 // -- ecx : name |
| 1455 // -- esp[0] : return address | 1736 // -- esp[0] : return address |
| 1456 // -- esp[4] : receiver | |
| 1457 // ----------------------------------- | 1737 // ----------------------------------- |
| 1458 Label miss; | 1738 Label miss; |
| 1459 | 1739 |
| 1460 __ mov(eax, Operand(esp, kPointerSize)); | |
| 1461 GenerateLoadField(object, holder, eax, ebx, edx, index, name, &miss); | 1740 GenerateLoadField(object, holder, eax, ebx, edx, index, name, &miss); |
| 1462 __ bind(&miss); | 1741 __ bind(&miss); |
| 1463 GenerateLoadMiss(masm(), Code::LOAD_IC); | 1742 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 1464 | 1743 |
| 1465 // Return the generated code. | 1744 // Return the generated code. |
| 1466 return GetCode(FIELD, name); | 1745 return GetCode(FIELD, name); |
| 1467 } | 1746 } |
| 1468 | 1747 |
| 1469 | 1748 |
| 1470 Object* LoadStubCompiler::CompileLoadCallback(String* name, | 1749 Object* LoadStubCompiler::CompileLoadCallback(String* name, |
| 1471 JSObject* object, | 1750 JSObject* object, |
| 1472 JSObject* holder, | 1751 JSObject* holder, |
| 1473 AccessorInfo* callback) { | 1752 AccessorInfo* callback) { |
| 1474 // ----------- S t a t e ------------- | 1753 // ----------- S t a t e ------------- |
| 1754 // -- eax : receiver |
| 1475 // -- ecx : name | 1755 // -- ecx : name |
| 1476 // -- esp[0] : return address | 1756 // -- esp[0] : return address |
| 1477 // -- esp[4] : receiver | |
| 1478 // ----------------------------------- | 1757 // ----------------------------------- |
| 1479 Label miss; | 1758 Label miss; |
| 1480 | 1759 |
| 1481 __ mov(eax, Operand(esp, kPointerSize)); | |
| 1482 Failure* failure = Failure::InternalError(); | 1760 Failure* failure = Failure::InternalError(); |
| 1483 bool success = GenerateLoadCallback(object, holder, eax, ecx, ebx, edx, | 1761 bool success = GenerateLoadCallback(object, holder, eax, ecx, ebx, edx, |
| 1484 callback, name, &miss, &failure); | 1762 callback, name, &miss, &failure); |
| 1485 if (!success) return failure; | 1763 if (!success) return failure; |
| 1486 | 1764 |
| 1487 __ bind(&miss); | 1765 __ bind(&miss); |
| 1488 GenerateLoadMiss(masm(), Code::LOAD_IC); | 1766 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 1489 | 1767 |
| 1490 // Return the generated code. | 1768 // Return the generated code. |
| 1491 return GetCode(CALLBACKS, name); | 1769 return GetCode(CALLBACKS, name); |
| 1492 } | 1770 } |
| 1493 | 1771 |
| 1494 | 1772 |
| 1495 Object* LoadStubCompiler::CompileLoadConstant(JSObject* object, | 1773 Object* LoadStubCompiler::CompileLoadConstant(JSObject* object, |
| 1496 JSObject* holder, | 1774 JSObject* holder, |
| 1497 Object* value, | 1775 Object* value, |
| 1498 String* name) { | 1776 String* name) { |
| 1499 // ----------- S t a t e ------------- | 1777 // ----------- S t a t e ------------- |
| 1778 // -- eax : receiver |
| 1500 // -- ecx : name | 1779 // -- ecx : name |
| 1501 // -- esp[0] : return address | 1780 // -- esp[0] : return address |
| 1502 // -- esp[4] : receiver | |
| 1503 // ----------------------------------- | 1781 // ----------------------------------- |
| 1504 Label miss; | 1782 Label miss; |
| 1505 | 1783 |
| 1506 __ mov(eax, Operand(esp, kPointerSize)); | |
| 1507 GenerateLoadConstant(object, holder, eax, ebx, edx, value, name, &miss); | 1784 GenerateLoadConstant(object, holder, eax, ebx, edx, value, name, &miss); |
| 1508 __ bind(&miss); | 1785 __ bind(&miss); |
| 1509 GenerateLoadMiss(masm(), Code::LOAD_IC); | 1786 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 1510 | 1787 |
| 1511 // Return the generated code. | 1788 // Return the generated code. |
| 1512 return GetCode(CONSTANT_FUNCTION, name); | 1789 return GetCode(CONSTANT_FUNCTION, name); |
| 1513 } | 1790 } |
| 1514 | 1791 |
| 1515 | 1792 |
| 1516 Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 1793 Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, |
| 1517 JSObject* holder, | 1794 JSObject* holder, |
| 1518 String* name) { | 1795 String* name) { |
| 1519 // ----------- S t a t e ------------- | 1796 // ----------- S t a t e ------------- |
| 1797 // -- eax : receiver |
| 1520 // -- ecx : name | 1798 // -- ecx : name |
| 1521 // -- esp[0] : return address | 1799 // -- esp[0] : return address |
| 1522 // -- esp[4] : receiver | |
| 1523 // ----------------------------------- | 1800 // ----------------------------------- |
| 1524 Label miss; | 1801 Label miss; |
| 1525 | 1802 |
| 1526 LookupResult lookup; | 1803 LookupResult lookup; |
| 1527 LookupPostInterceptor(holder, name, &lookup); | 1804 LookupPostInterceptor(holder, name, &lookup); |
| 1528 | 1805 |
| 1529 __ mov(eax, Operand(esp, kPointerSize)); | |
| 1530 // TODO(368): Compile in the whole chain: all the interceptors in | 1806 // TODO(368): Compile in the whole chain: all the interceptors in |
| 1531 // prototypes and ultimate answer. | 1807 // prototypes and ultimate answer. |
| 1532 GenerateLoadInterceptor(receiver, | 1808 GenerateLoadInterceptor(receiver, |
| 1533 holder, | 1809 holder, |
| 1534 &lookup, | 1810 &lookup, |
| 1535 eax, | 1811 eax, |
| 1536 ecx, | 1812 ecx, |
| 1537 edx, | 1813 edx, |
| 1538 ebx, | 1814 ebx, |
| 1539 name, | 1815 name, |
| 1540 &miss); | 1816 &miss); |
| 1541 | 1817 |
| 1542 __ bind(&miss); | 1818 __ bind(&miss); |
| 1543 GenerateLoadMiss(masm(), Code::LOAD_IC); | 1819 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 1544 | 1820 |
| 1545 // Return the generated code. | 1821 // Return the generated code. |
| 1546 return GetCode(INTERCEPTOR, name); | 1822 return GetCode(INTERCEPTOR, name); |
| 1547 } | 1823 } |
| 1548 | 1824 |
| 1549 | 1825 |
| 1550 Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object, | 1826 Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object, |
| 1551 GlobalObject* holder, | 1827 GlobalObject* holder, |
| 1552 JSGlobalPropertyCell* cell, | 1828 JSGlobalPropertyCell* cell, |
| 1553 String* name, | 1829 String* name, |
| 1554 bool is_dont_delete) { | 1830 bool is_dont_delete) { |
| 1555 // ----------- S t a t e ------------- | 1831 // ----------- S t a t e ------------- |
| 1832 // -- eax : receiver |
| 1556 // -- ecx : name | 1833 // -- ecx : name |
| 1557 // -- esp[0] : return address | 1834 // -- esp[0] : return address |
| 1558 // -- esp[4] : receiver | |
| 1559 // ----------------------------------- | 1835 // ----------------------------------- |
| 1560 Label miss; | 1836 Label miss; |
| 1561 | 1837 |
| 1562 // Get the receiver from the stack. | |
| 1563 __ mov(eax, Operand(esp, kPointerSize)); | |
| 1564 | |
| 1565 // If the object is the holder then we know that it's a global | 1838 // If the object is the holder then we know that it's a global |
| 1566 // object which can only happen for contextual loads. In this case, | 1839 // object which can only happen for contextual loads. In this case, |
| 1567 // the receiver cannot be a smi. | 1840 // the receiver cannot be a smi. |
| 1568 if (object != holder) { | 1841 if (object != holder) { |
| 1569 __ test(eax, Immediate(kSmiTagMask)); | 1842 __ test(eax, Immediate(kSmiTagMask)); |
| 1570 __ j(zero, &miss, not_taken); | 1843 __ j(zero, &miss, not_taken); |
| 1571 } | 1844 } |
| 1572 | 1845 |
| 1573 // Check that the maps haven't changed. | 1846 // Check that the maps haven't changed. |
| 1574 CheckPrototypes(object, eax, holder, ebx, edx, name, &miss); | 1847 CheckPrototypes(object, eax, holder, ebx, edx, name, &miss); |
| 1575 | 1848 |
| 1576 // Get the value from the cell. | 1849 // Get the value from the cell. |
| 1577 __ mov(eax, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 1850 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); |
| 1578 __ mov(eax, FieldOperand(eax, JSGlobalPropertyCell::kValueOffset)); | 1851 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); |
| 1579 | 1852 |
| 1580 // Check for deleted property if property can actually be deleted. | 1853 // Check for deleted property if property can actually be deleted. |
| 1581 if (!is_dont_delete) { | 1854 if (!is_dont_delete) { |
| 1582 __ cmp(eax, Factory::the_hole_value()); | 1855 __ cmp(ebx, Factory::the_hole_value()); |
| 1583 __ j(equal, &miss, not_taken); | 1856 __ j(equal, &miss, not_taken); |
| 1584 } else if (FLAG_debug_code) { | 1857 } else if (FLAG_debug_code) { |
| 1585 __ cmp(eax, Factory::the_hole_value()); | 1858 __ cmp(ebx, Factory::the_hole_value()); |
| 1586 __ Check(not_equal, "DontDelete cells can't contain the hole"); | 1859 __ Check(not_equal, "DontDelete cells can't contain the hole"); |
| 1587 } | 1860 } |
| 1588 | 1861 |
| 1589 __ IncrementCounter(&Counters::named_load_global_inline, 1); | 1862 __ IncrementCounter(&Counters::named_load_global_inline, 1); |
| 1863 __ mov(eax, ebx); |
| 1590 __ ret(0); | 1864 __ ret(0); |
| 1591 | 1865 |
| 1592 __ bind(&miss); | 1866 __ bind(&miss); |
| 1593 __ IncrementCounter(&Counters::named_load_global_inline_miss, 1); | 1867 __ IncrementCounter(&Counters::named_load_global_inline_miss, 1); |
| 1594 GenerateLoadMiss(masm(), Code::LOAD_IC); | 1868 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 1595 | 1869 |
| 1596 // Return the generated code. | 1870 // Return the generated code. |
| 1597 return GetCode(NORMAL, name); | 1871 return GetCode(NORMAL, name); |
| 1598 } | 1872 } |
| 1599 | 1873 |
| 1600 | 1874 |
| 1601 Object* KeyedLoadStubCompiler::CompileLoadField(String* name, | 1875 Object* KeyedLoadStubCompiler::CompileLoadField(String* name, |
| 1602 JSObject* receiver, | 1876 JSObject* receiver, |
| 1603 JSObject* holder, | 1877 JSObject* holder, |
| 1604 int index) { | 1878 int index) { |
| 1605 // ----------- S t a t e ------------- | 1879 // ----------- S t a t e ------------- |
| 1880 // -- eax : key |
| 1881 // -- edx : receiver |
| 1606 // -- esp[0] : return address | 1882 // -- esp[0] : return address |
| 1607 // -- esp[4] : name | |
| 1608 // -- esp[8] : receiver | |
| 1609 // ----------------------------------- | 1883 // ----------------------------------- |
| 1610 Label miss; | 1884 Label miss; |
| 1611 | 1885 |
| 1612 __ mov(eax, Operand(esp, kPointerSize)); | |
| 1613 __ mov(ecx, Operand(esp, 2 * kPointerSize)); | |
| 1614 __ IncrementCounter(&Counters::keyed_load_field, 1); | 1886 __ IncrementCounter(&Counters::keyed_load_field, 1); |
| 1615 | 1887 |
| 1616 // Check that the name has not changed. | 1888 // Check that the name has not changed. |
| 1617 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 1889 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 1618 __ j(not_equal, &miss, not_taken); | 1890 __ j(not_equal, &miss, not_taken); |
| 1619 | 1891 |
| 1620 GenerateLoadField(receiver, holder, ecx, ebx, edx, index, name, &miss); | 1892 GenerateLoadField(receiver, holder, edx, ebx, ecx, index, name, &miss); |
| 1621 | 1893 |
| 1622 __ bind(&miss); | 1894 __ bind(&miss); |
| 1623 __ DecrementCounter(&Counters::keyed_load_field, 1); | 1895 __ DecrementCounter(&Counters::keyed_load_field, 1); |
| 1624 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 1896 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 1625 | 1897 |
| 1626 // Return the generated code. | 1898 // Return the generated code. |
| 1627 return GetCode(FIELD, name); | 1899 return GetCode(FIELD, name); |
| 1628 } | 1900 } |
| 1629 | 1901 |
| 1630 | 1902 |
| 1631 Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name, | 1903 Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name, |
| 1632 JSObject* receiver, | 1904 JSObject* receiver, |
| 1633 JSObject* holder, | 1905 JSObject* holder, |
| 1634 AccessorInfo* callback) { | 1906 AccessorInfo* callback) { |
| 1635 // ----------- S t a t e ------------- | 1907 // ----------- S t a t e ------------- |
| 1908 // -- eax : key |
| 1909 // -- edx : receiver |
| 1636 // -- esp[0] : return address | 1910 // -- esp[0] : return address |
| 1637 // -- esp[4] : name | |
| 1638 // -- esp[8] : receiver | |
| 1639 // ----------------------------------- | 1911 // ----------------------------------- |
| 1640 Label miss; | 1912 Label miss; |
| 1641 | 1913 |
| 1642 __ mov(eax, Operand(esp, kPointerSize)); | |
| 1643 __ mov(ecx, Operand(esp, 2 * kPointerSize)); | |
| 1644 __ IncrementCounter(&Counters::keyed_load_callback, 1); | 1914 __ IncrementCounter(&Counters::keyed_load_callback, 1); |
| 1645 | 1915 |
| 1646 // Check that the name has not changed. | 1916 // Check that the name has not changed. |
| 1647 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 1917 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 1648 __ j(not_equal, &miss, not_taken); | 1918 __ j(not_equal, &miss, not_taken); |
| 1649 | 1919 |
| 1650 Failure* failure = Failure::InternalError(); | 1920 Failure* failure = Failure::InternalError(); |
| 1651 bool success = GenerateLoadCallback(receiver, holder, ecx, eax, ebx, edx, | 1921 bool success = GenerateLoadCallback(receiver, holder, edx, eax, ebx, ecx, |
| 1652 callback, name, &miss, &failure); | 1922 callback, name, &miss, &failure); |
| 1653 if (!success) return failure; | 1923 if (!success) return failure; |
| 1654 | 1924 |
| 1655 __ bind(&miss); | 1925 __ bind(&miss); |
| 1656 __ DecrementCounter(&Counters::keyed_load_callback, 1); | 1926 __ DecrementCounter(&Counters::keyed_load_callback, 1); |
| 1657 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 1927 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 1658 | 1928 |
| 1659 // Return the generated code. | 1929 // Return the generated code. |
| 1660 return GetCode(CALLBACKS, name); | 1930 return GetCode(CALLBACKS, name); |
| 1661 } | 1931 } |
| 1662 | 1932 |
| 1663 | 1933 |
| 1664 Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name, | 1934 Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name, |
| 1665 JSObject* receiver, | 1935 JSObject* receiver, |
| 1666 JSObject* holder, | 1936 JSObject* holder, |
| 1667 Object* value) { | 1937 Object* value) { |
| 1668 // ----------- S t a t e ------------- | 1938 // ----------- S t a t e ------------- |
| 1939 // -- eax : key |
| 1940 // -- edx : receiver |
| 1669 // -- esp[0] : return address | 1941 // -- esp[0] : return address |
| 1670 // -- esp[4] : name | |
| 1671 // -- esp[8] : receiver | |
| 1672 // ----------------------------------- | 1942 // ----------------------------------- |
| 1673 Label miss; | 1943 Label miss; |
| 1674 | 1944 |
| 1675 __ mov(eax, Operand(esp, kPointerSize)); | |
| 1676 __ mov(ecx, Operand(esp, 2 * kPointerSize)); | |
| 1677 __ IncrementCounter(&Counters::keyed_load_constant_function, 1); | 1945 __ IncrementCounter(&Counters::keyed_load_constant_function, 1); |
| 1678 | 1946 |
| 1679 // Check that the name has not changed. | 1947 // Check that the name has not changed. |
| 1680 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 1948 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 1681 __ j(not_equal, &miss, not_taken); | 1949 __ j(not_equal, &miss, not_taken); |
| 1682 | 1950 |
| 1683 GenerateLoadConstant(receiver, holder, ecx, ebx, edx, | 1951 GenerateLoadConstant(receiver, holder, edx, ebx, ecx, |
| 1684 value, name, &miss); | 1952 value, name, &miss); |
| 1685 __ bind(&miss); | 1953 __ bind(&miss); |
| 1686 __ DecrementCounter(&Counters::keyed_load_constant_function, 1); | 1954 __ DecrementCounter(&Counters::keyed_load_constant_function, 1); |
| 1687 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 1955 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 1688 | 1956 |
| 1689 // Return the generated code. | 1957 // Return the generated code. |
| 1690 return GetCode(CONSTANT_FUNCTION, name); | 1958 return GetCode(CONSTANT_FUNCTION, name); |
| 1691 } | 1959 } |
| 1692 | 1960 |
| 1693 | 1961 |
| 1694 Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 1962 Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, |
| 1695 JSObject* holder, | 1963 JSObject* holder, |
| 1696 String* name) { | 1964 String* name) { |
| 1697 // ----------- S t a t e ------------- | 1965 // ----------- S t a t e ------------- |
| 1966 // -- eax : key |
| 1967 // -- edx : receiver |
| 1698 // -- esp[0] : return address | 1968 // -- esp[0] : return address |
| 1699 // -- esp[4] : name | |
| 1700 // -- esp[8] : receiver | |
| 1701 // ----------------------------------- | 1969 // ----------------------------------- |
| 1702 Label miss; | 1970 Label miss; |
| 1703 | 1971 |
| 1704 __ mov(eax, Operand(esp, kPointerSize)); | |
| 1705 __ mov(ecx, Operand(esp, 2 * kPointerSize)); | |
| 1706 __ IncrementCounter(&Counters::keyed_load_interceptor, 1); | 1972 __ IncrementCounter(&Counters::keyed_load_interceptor, 1); |
| 1707 | 1973 |
| 1708 // Check that the name has not changed. | 1974 // Check that the name has not changed. |
| 1709 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 1975 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 1710 __ j(not_equal, &miss, not_taken); | 1976 __ j(not_equal, &miss, not_taken); |
| 1711 | 1977 |
| 1712 LookupResult lookup; | 1978 LookupResult lookup; |
| 1713 LookupPostInterceptor(holder, name, &lookup); | 1979 LookupPostInterceptor(holder, name, &lookup); |
| 1714 GenerateLoadInterceptor(receiver, | 1980 GenerateLoadInterceptor(receiver, |
| 1715 holder, | 1981 holder, |
| 1716 &lookup, | 1982 &lookup, |
| 1983 edx, |
| 1984 eax, |
| 1717 ecx, | 1985 ecx, |
| 1718 eax, | |
| 1719 edx, | |
| 1720 ebx, | 1986 ebx, |
| 1721 name, | 1987 name, |
| 1722 &miss); | 1988 &miss); |
| 1723 __ bind(&miss); | 1989 __ bind(&miss); |
| 1724 __ DecrementCounter(&Counters::keyed_load_interceptor, 1); | 1990 __ DecrementCounter(&Counters::keyed_load_interceptor, 1); |
| 1725 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 1991 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 1726 | 1992 |
| 1727 // Return the generated code. | 1993 // Return the generated code. |
| 1728 return GetCode(INTERCEPTOR, name); | 1994 return GetCode(INTERCEPTOR, name); |
| 1729 } | 1995 } |
| 1730 | 1996 |
| 1731 | 1997 |
| 1732 | 1998 |
| 1733 | 1999 |
| 1734 Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) { | 2000 Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) { |
| 1735 // ----------- S t a t e ------------- | 2001 // ----------- S t a t e ------------- |
| 2002 // -- eax : key |
| 2003 // -- edx : receiver |
| 1736 // -- esp[0] : return address | 2004 // -- esp[0] : return address |
| 1737 // -- esp[4] : name | |
| 1738 // -- esp[8] : receiver | |
| 1739 // ----------------------------------- | 2005 // ----------------------------------- |
| 1740 Label miss; | 2006 Label miss; |
| 1741 | 2007 |
| 1742 __ mov(eax, Operand(esp, kPointerSize)); | |
| 1743 __ mov(ecx, Operand(esp, 2 * kPointerSize)); | |
| 1744 __ IncrementCounter(&Counters::keyed_load_array_length, 1); | 2008 __ IncrementCounter(&Counters::keyed_load_array_length, 1); |
| 1745 | 2009 |
| 1746 // Check that the name has not changed. | 2010 // Check that the name has not changed. |
| 1747 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 2011 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 1748 __ j(not_equal, &miss, not_taken); | 2012 __ j(not_equal, &miss, not_taken); |
| 1749 | 2013 |
| 1750 GenerateLoadArrayLength(masm(), ecx, edx, &miss); | 2014 GenerateLoadArrayLength(masm(), edx, ecx, &miss); |
| 1751 __ bind(&miss); | 2015 __ bind(&miss); |
| 1752 __ DecrementCounter(&Counters::keyed_load_array_length, 1); | 2016 __ DecrementCounter(&Counters::keyed_load_array_length, 1); |
| 1753 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2017 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 1754 | 2018 |
| 1755 // Return the generated code. | 2019 // Return the generated code. |
| 1756 return GetCode(CALLBACKS, name); | 2020 return GetCode(CALLBACKS, name); |
| 1757 } | 2021 } |
| 1758 | 2022 |
| 1759 | 2023 |
| 1760 Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { | 2024 Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { |
| 1761 // ----------- S t a t e ------------- | 2025 // ----------- S t a t e ------------- |
| 2026 // -- eax : key |
| 2027 // -- edx : receiver |
| 1762 // -- esp[0] : return address | 2028 // -- esp[0] : return address |
| 1763 // -- esp[4] : name | |
| 1764 // -- esp[8] : receiver | |
| 1765 // ----------------------------------- | 2029 // ----------------------------------- |
| 1766 Label miss; | 2030 Label miss; |
| 1767 | 2031 |
| 1768 __ mov(eax, Operand(esp, kPointerSize)); | |
| 1769 __ mov(ecx, Operand(esp, 2 * kPointerSize)); | |
| 1770 __ IncrementCounter(&Counters::keyed_load_string_length, 1); | 2032 __ IncrementCounter(&Counters::keyed_load_string_length, 1); |
| 1771 | 2033 |
| 1772 // Check that the name has not changed. | 2034 // Check that the name has not changed. |
| 1773 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 2035 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 1774 __ j(not_equal, &miss, not_taken); | 2036 __ j(not_equal, &miss, not_taken); |
| 1775 | 2037 |
| 1776 GenerateLoadStringLength(masm(), ecx, edx, &miss); | 2038 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss); |
| 1777 __ bind(&miss); | 2039 __ bind(&miss); |
| 1778 __ DecrementCounter(&Counters::keyed_load_string_length, 1); | 2040 __ DecrementCounter(&Counters::keyed_load_string_length, 1); |
| 1779 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2041 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 1780 | 2042 |
| 1781 // Return the generated code. | 2043 // Return the generated code. |
| 1782 return GetCode(CALLBACKS, name); | 2044 return GetCode(CALLBACKS, name); |
| 1783 } | 2045 } |
| 1784 | 2046 |
| 1785 | 2047 |
| 1786 Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { | 2048 Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { |
| 1787 // ----------- S t a t e ------------- | 2049 // ----------- S t a t e ------------- |
| 2050 // -- eax : key |
| 2051 // -- edx : receiver |
| 1788 // -- esp[0] : return address | 2052 // -- esp[0] : return address |
| 1789 // -- esp[4] : name | |
| 1790 // -- esp[8] : receiver | |
| 1791 // ----------------------------------- | 2053 // ----------------------------------- |
| 1792 Label miss; | 2054 Label miss; |
| 1793 | 2055 |
| 1794 __ mov(eax, Operand(esp, kPointerSize)); | |
| 1795 __ mov(ecx, Operand(esp, 2 * kPointerSize)); | |
| 1796 __ IncrementCounter(&Counters::keyed_load_function_prototype, 1); | 2056 __ IncrementCounter(&Counters::keyed_load_function_prototype, 1); |
| 1797 | 2057 |
| 1798 // Check that the name has not changed. | 2058 // Check that the name has not changed. |
| 1799 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 2059 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 1800 __ j(not_equal, &miss, not_taken); | 2060 __ j(not_equal, &miss, not_taken); |
| 1801 | 2061 |
| 1802 GenerateLoadFunctionPrototype(masm(), ecx, edx, ebx, &miss); | 2062 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); |
| 1803 __ bind(&miss); | 2063 __ bind(&miss); |
| 1804 __ DecrementCounter(&Counters::keyed_load_function_prototype, 1); | 2064 __ DecrementCounter(&Counters::keyed_load_function_prototype, 1); |
| 1805 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2065 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 1806 | 2066 |
| 1807 // Return the generated code. | 2067 // Return the generated code. |
| 1808 return GetCode(CALLBACKS, name); | 2068 return GetCode(CALLBACKS, name); |
| 1809 } | 2069 } |
| 1810 | 2070 |
| 1811 | 2071 |
| 1812 // Specialized stub for constructing objects from functions which only have only | 2072 // Specialized stub for constructing objects from functions which only have only |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1942 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); | 2202 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); |
| 1943 | 2203 |
| 1944 // Return the generated code. | 2204 // Return the generated code. |
| 1945 return GetCode(); | 2205 return GetCode(); |
| 1946 } | 2206 } |
| 1947 | 2207 |
| 1948 | 2208 |
| 1949 #undef __ | 2209 #undef __ |
| 1950 | 2210 |
| 1951 } } // namespace v8::internal | 2211 } } // namespace v8::internal |
| OLD | NEW |