OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 |
11 // with the distribution. | 11 // with the distribution. |
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 Handle<JSObject> object, | 369 Handle<JSObject> object, |
370 int index, | 370 int index, |
371 Handle<Map> transition, | 371 Handle<Map> transition, |
372 Register receiver_reg, | 372 Register receiver_reg, |
373 Register name_reg, | 373 Register name_reg, |
374 Register scratch, | 374 Register scratch, |
375 Label* miss_label) { | 375 Label* miss_label) { |
376 // r0 : value | 376 // r0 : value |
377 Label exit; | 377 Label exit; |
378 | 378 |
379 // Check that the receiver isn't a smi. | 379 // Check that the map of the object hasn't changed. |
380 __ JumpIfSmi(receiver_reg, miss_label); | 380 __ CheckMap(receiver_reg, scratch, Handle<Map>(object->map()), miss_label, |
381 | 381 DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); |
382 // Check that the map of the receiver hasn't changed. | |
383 __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); | |
384 __ cmp(scratch, Operand(Handle<Map>(object->map()))); | |
385 __ b(ne, miss_label); | |
386 | 382 |
387 // Perform global security token check if needed. | 383 // Perform global security token check if needed. |
388 if (object->IsJSGlobalProxy()) { | 384 if (object->IsJSGlobalProxy()) { |
389 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); | 385 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); |
390 } | 386 } |
391 | 387 |
392 // Stub never generated for non-global objects that require access | 388 // Stub never generated for non-global objects that require access |
393 // checks. | 389 // checks. |
394 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 390 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
395 | 391 |
(...skipping 616 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1012 StringDictionary::kNotFound); | 1008 StringDictionary::kNotFound); |
1013 | 1009 |
1014 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, | 1010 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, |
1015 scratch1, scratch2); | 1011 scratch1, scratch2); |
1016 | 1012 |
1017 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | 1013 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
1018 reg = holder_reg; // From now on the object will be in holder_reg. | 1014 reg = holder_reg; // From now on the object will be in holder_reg. |
1019 __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | 1015 __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
1020 } else { | 1016 } else { |
1021 Handle<Map> current_map(current->map()); | 1017 Handle<Map> current_map(current->map()); |
1022 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | 1018 __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK, |
1023 __ cmp(scratch1, Operand(current_map)); | 1019 ALLOW_ELEMENT_TRANSITION_MAPS); |
1024 // Branch on the result of the map check. | 1020 |
1025 __ b(ne, miss); | |
1026 // Check access rights to the global object. This has to happen after | 1021 // Check access rights to the global object. This has to happen after |
1027 // the map check so that we know that the object is actually a global | 1022 // the map check so that we know that the object is actually a global |
1028 // object. | 1023 // object. |
1029 if (current->IsJSGlobalProxy()) { | 1024 if (current->IsJSGlobalProxy()) { |
1030 __ CheckAccessGlobalProxy(reg, scratch2, miss); | 1025 __ CheckAccessGlobalProxy(reg, scratch2, miss); |
1031 } | 1026 } |
1032 reg = holder_reg; // From now on the object will be in holder_reg. | 1027 reg = holder_reg; // From now on the object will be in holder_reg. |
1033 | 1028 |
1034 if (heap()->InNewSpace(*prototype)) { | 1029 if (heap()->InNewSpace(*prototype)) { |
1035 // The prototype is in new space; we cannot store a reference to it | 1030 // The prototype is in new space; we cannot store a reference to it |
(...skipping 10 matching lines...) Expand all Loading... |
1046 } | 1041 } |
1047 | 1042 |
1048 // Go to the next object in the prototype chain. | 1043 // Go to the next object in the prototype chain. |
1049 current = prototype; | 1044 current = prototype; |
1050 } | 1045 } |
1051 | 1046 |
1052 // Log the check depth. | 1047 // Log the check depth. |
1053 LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1)); | 1048 LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1)); |
1054 | 1049 |
1055 // Check the holder map. | 1050 // Check the holder map. |
1056 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | 1051 __ CheckMap(reg, scratch1, Handle<Map>(current->map()), miss, |
1057 __ cmp(scratch1, Operand(Handle<Map>(current->map()))); | 1052 DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); |
1058 __ b(ne, miss); | |
1059 | 1053 |
1060 // Perform security check for access to the global object. | 1054 // Perform security check for access to the global object. |
1061 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1055 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
1062 if (holder->IsJSGlobalProxy()) { | 1056 if (holder->IsJSGlobalProxy()) { |
1063 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 1057 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
1064 } | 1058 } |
1065 | 1059 |
1066 // If we've skipped any global objects, it's not enough to verify that | 1060 // If we've skipped any global objects, it's not enough to verify that |
1067 // their maps haven't changed. We also need to check that the property | 1061 // their maps haven't changed. We also need to check that the property |
1068 // cell for the property is still empty. | 1062 // cell for the property is still empty. |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1143 __ Move(scratch3, Handle<Object>(callback->data())); | 1137 __ Move(scratch3, Handle<Object>(callback->data())); |
1144 } | 1138 } |
1145 __ Push(reg, scratch3, name_reg); | 1139 __ Push(reg, scratch3, name_reg); |
1146 __ mov(r0, sp); // r0 = Handle<String> | 1140 __ mov(r0, sp); // r0 = Handle<String> |
1147 | 1141 |
1148 const int kApiStackSpace = 1; | 1142 const int kApiStackSpace = 1; |
1149 FrameScope frame_scope(masm(), StackFrame::MANUAL); | 1143 FrameScope frame_scope(masm(), StackFrame::MANUAL); |
1150 __ EnterExitFrame(false, kApiStackSpace); | 1144 __ EnterExitFrame(false, kApiStackSpace); |
1151 | 1145 |
1152 // Create AccessorInfo instance on the stack above the exit frame with | 1146 // Create AccessorInfo instance on the stack above the exit frame with |
1153 // scratch2 (internal::Object **args_) as the data. | 1147 // scratch2 (internal::Object** args_) as the data. |
1154 __ str(scratch2, MemOperand(sp, 1 * kPointerSize)); | 1148 __ str(scratch2, MemOperand(sp, 1 * kPointerSize)); |
1155 __ add(r1, sp, Operand(1 * kPointerSize)); // r1 = AccessorInfo& | 1149 __ add(r1, sp, Operand(1 * kPointerSize)); // r1 = AccessorInfo& |
1156 | 1150 |
1157 const int kStackUnwindSpace = 4; | 1151 const int kStackUnwindSpace = 4; |
1158 Address getter_address = v8::ToCData<Address>(callback->getter()); | 1152 Address getter_address = v8::ToCData<Address>(callback->getter()); |
1159 ApiFunction fun(getter_address); | 1153 ApiFunction fun(getter_address); |
1160 ExternalReference ref = | 1154 ExternalReference ref = |
1161 ExternalReference(&fun, | 1155 ExternalReference(&fun, |
1162 ExternalReference::DIRECT_GETTER_CALL, | 1156 ExternalReference::DIRECT_GETTER_CALL, |
1163 masm()->isolate()); | 1157 masm()->isolate()); |
(...skipping 1240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2404 GenerateGlobalReceiverCheck(object, holder, name, &miss); | 2398 GenerateGlobalReceiverCheck(object, holder, name, &miss); |
2405 GenerateLoadFunctionFromCell(cell, function, &miss); | 2399 GenerateLoadFunctionFromCell(cell, function, &miss); |
2406 | 2400 |
2407 // Patch the receiver on the stack with the global proxy if | 2401 // Patch the receiver on the stack with the global proxy if |
2408 // necessary. | 2402 // necessary. |
2409 if (object->IsGlobalObject()) { | 2403 if (object->IsGlobalObject()) { |
2410 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); | 2404 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); |
2411 __ str(r3, MemOperand(sp, argc * kPointerSize)); | 2405 __ str(r3, MemOperand(sp, argc * kPointerSize)); |
2412 } | 2406 } |
2413 | 2407 |
2414 // Setup the context (function already in r1). | 2408 // Set up the context (function already in r1). |
2415 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 2409 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
2416 | 2410 |
2417 // Jump to the cached code (tail call). | 2411 // Jump to the cached code (tail call). |
2418 Counters* counters = masm()->isolate()->counters(); | 2412 Counters* counters = masm()->isolate()->counters(); |
2419 __ IncrementCounter(counters->call_global_inline(), 1, r3, r4); | 2413 __ IncrementCounter(counters->call_global_inline(), 1, r3, r4); |
2420 ParameterCount expected(function->shared()->formal_parameter_count()); | 2414 ParameterCount expected(function->shared()->formal_parameter_count()); |
2421 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2415 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
2422 ? CALL_AS_FUNCTION | 2416 ? CALL_AS_FUNCTION |
2423 : CALL_AS_METHOD; | 2417 : CALL_AS_METHOD; |
2424 // We call indirectly through the code field in the function to | 2418 // We call indirectly through the code field in the function to |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2465 Handle<AccessorInfo> callback, | 2459 Handle<AccessorInfo> callback, |
2466 Handle<String> name) { | 2460 Handle<String> name) { |
2467 // ----------- S t a t e ------------- | 2461 // ----------- S t a t e ------------- |
2468 // -- r0 : value | 2462 // -- r0 : value |
2469 // -- r1 : receiver | 2463 // -- r1 : receiver |
2470 // -- r2 : name | 2464 // -- r2 : name |
2471 // -- lr : return address | 2465 // -- lr : return address |
2472 // ----------------------------------- | 2466 // ----------------------------------- |
2473 Label miss; | 2467 Label miss; |
2474 | 2468 |
2475 // Check that the object isn't a smi. | |
2476 __ JumpIfSmi(r1, &miss); | |
2477 | |
2478 // Check that the map of the object hasn't changed. | 2469 // Check that the map of the object hasn't changed. |
2479 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); | 2470 __ CheckMap(r1, r3, Handle<Map>(object->map()), &miss, |
2480 __ cmp(r3, Operand(Handle<Map>(object->map()))); | 2471 DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); |
2481 __ b(ne, &miss); | |
2482 | 2472 |
2483 // Perform global security token check if needed. | 2473 // Perform global security token check if needed. |
2484 if (object->IsJSGlobalProxy()) { | 2474 if (object->IsJSGlobalProxy()) { |
2485 __ CheckAccessGlobalProxy(r1, r3, &miss); | 2475 __ CheckAccessGlobalProxy(r1, r3, &miss); |
2486 } | 2476 } |
2487 | 2477 |
2488 // Stub never generated for non-global objects that require access | 2478 // Stub never generated for non-global objects that require access |
2489 // checks. | 2479 // checks. |
2490 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 2480 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
2491 | 2481 |
(...skipping 21 matching lines...) Expand all Loading... |
2513 Handle<JSObject> receiver, | 2503 Handle<JSObject> receiver, |
2514 Handle<String> name) { | 2504 Handle<String> name) { |
2515 // ----------- S t a t e ------------- | 2505 // ----------- S t a t e ------------- |
2516 // -- r0 : value | 2506 // -- r0 : value |
2517 // -- r1 : receiver | 2507 // -- r1 : receiver |
2518 // -- r2 : name | 2508 // -- r2 : name |
2519 // -- lr : return address | 2509 // -- lr : return address |
2520 // ----------------------------------- | 2510 // ----------------------------------- |
2521 Label miss; | 2511 Label miss; |
2522 | 2512 |
2523 // Check that the object isn't a smi. | |
2524 __ JumpIfSmi(r1, &miss); | |
2525 | |
2526 // Check that the map of the object hasn't changed. | 2513 // Check that the map of the object hasn't changed. |
2527 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); | 2514 __ CheckMap(r1, r3, Handle<Map>(receiver->map()), &miss, |
2528 __ cmp(r3, Operand(Handle<Map>(receiver->map()))); | 2515 DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); |
2529 __ b(ne, &miss); | |
2530 | 2516 |
2531 // Perform global security token check if needed. | 2517 // Perform global security token check if needed. |
2532 if (receiver->IsJSGlobalProxy()) { | 2518 if (receiver->IsJSGlobalProxy()) { |
2533 __ CheckAccessGlobalProxy(r1, r3, &miss); | 2519 __ CheckAccessGlobalProxy(r1, r3, &miss); |
2534 } | 2520 } |
2535 | 2521 |
2536 // Stub is never generated for non-global objects that require access | 2522 // Stub is never generated for non-global objects that require access |
2537 // checks. | 2523 // checks. |
2538 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); | 2524 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); |
2539 | 2525 |
(...skipping 1686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4226 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); | 4212 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
4227 __ Jump(ic_miss, RelocInfo::CODE_TARGET); | 4213 __ Jump(ic_miss, RelocInfo::CODE_TARGET); |
4228 } | 4214 } |
4229 | 4215 |
4230 | 4216 |
4231 #undef __ | 4217 #undef __ |
4232 | 4218 |
4233 } } // namespace v8::internal | 4219 } } // namespace v8::internal |
4234 | 4220 |
4235 #endif // V8_TARGET_ARCH_ARM | 4221 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |