OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 7868 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7879 | 7879 |
7880 static inline MaybeObject* Unhole(Heap* heap, | 7880 static inline MaybeObject* Unhole(Heap* heap, |
7881 MaybeObject* x, | 7881 MaybeObject* x, |
7882 PropertyAttributes attributes) { | 7882 PropertyAttributes attributes) { |
7883 ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0); | 7883 ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0); |
7884 USE(attributes); | 7884 USE(attributes); |
7885 return x->IsTheHole() ? heap->undefined_value() : x; | 7885 return x->IsTheHole() ? heap->undefined_value() : x; |
7886 } | 7886 } |
7887 | 7887 |
7888 | 7888 |
7889 static JSObject* ComputeReceiverForNonGlobal(Isolate* isolate, | 7889 static Object* ComputeReceiverForNonGlobal(Isolate* isolate, |
7890 JSObject* holder) { | 7890 JSObject* holder) { |
7891 ASSERT(!holder->IsGlobalObject()); | 7891 ASSERT(!holder->IsGlobalObject()); |
7892 Context* top = isolate->context(); | 7892 Context* top = isolate->context(); |
7893 // Get the context extension function. | 7893 // Get the context extension function. |
7894 JSFunction* context_extension_function = | 7894 JSFunction* context_extension_function = |
7895 top->global_context()->context_extension_function(); | 7895 top->global_context()->context_extension_function(); |
7896 // If the holder isn't a context extension object, we just return it | 7896 // If the holder isn't a context extension object, we just return it |
7897 // as the receiver. This allows arguments objects to be used as | 7897 // as the receiver. This allows arguments objects to be used as |
7898 // receivers, but only if they are put in the context scope chain | 7898 // receivers, but only if they are put in the context scope chain |
7899 // explicitly via a with-statement. | 7899 // explicitly via a with-statement. |
7900 Object* constructor = holder->map()->constructor(); | 7900 Object* constructor = holder->map()->constructor(); |
7901 if (constructor != context_extension_function) return holder; | 7901 if (constructor != context_extension_function) return holder; |
7902 // Fall back to using the global object as the receiver if the | 7902 // Fall back to using the global object as the implicit receiver if |
7903 // property turns out to be a local variable allocated in a context | 7903 // the property turns out to be a local variable allocated in a |
7904 // extension object - introduced via eval. | 7904 // context extension object - introduced via eval. Implicit global |
7905 return top->global()->global_receiver(); | 7905 // receivers are indicated with the hole value. |
| 7906 return isolate->heap()->the_hole_value(); |
7906 } | 7907 } |
7907 | 7908 |
7908 | 7909 |
7909 static ObjectPair LoadContextSlotHelper(Arguments args, | 7910 static ObjectPair LoadContextSlotHelper(Arguments args, |
7910 Isolate* isolate, | 7911 Isolate* isolate, |
7911 bool throw_error) { | 7912 bool throw_error) { |
7912 HandleScope scope(isolate); | 7913 HandleScope scope(isolate); |
7913 ASSERT_EQ(2, args.length()); | 7914 ASSERT_EQ(2, args.length()); |
7914 | 7915 |
7915 if (!args[0]->IsContext() || !args[1]->IsString()) { | 7916 if (!args[0]->IsContext() || !args[1]->IsString()) { |
7916 return MakePair(isolate->ThrowIllegalOperation(), NULL); | 7917 return MakePair(isolate->ThrowIllegalOperation(), NULL); |
7917 } | 7918 } |
7918 Handle<Context> context = args.at<Context>(0); | 7919 Handle<Context> context = args.at<Context>(0); |
7919 Handle<String> name = args.at<String>(1); | 7920 Handle<String> name = args.at<String>(1); |
7920 | 7921 |
7921 int index; | 7922 int index; |
7922 PropertyAttributes attributes; | 7923 PropertyAttributes attributes; |
7923 ContextLookupFlags flags = FOLLOW_CHAINS; | 7924 ContextLookupFlags flags = FOLLOW_CHAINS; |
7924 Handle<Object> holder = context->Lookup(name, flags, &index, &attributes); | 7925 Handle<Object> holder = context->Lookup(name, flags, &index, &attributes); |
7925 | 7926 |
7926 // If the index is non-negative, the slot has been found in a local | 7927 // If the index is non-negative, the slot has been found in a local |
7927 // variable or a parameter. Read it from the context object or the | 7928 // variable or a parameter. Read it from the context object or the |
7928 // arguments object. | 7929 // arguments object. |
7929 if (index >= 0) { | 7930 if (index >= 0) { |
7930 // If the "property" we were looking for is a local variable or an | 7931 // If the "property" we were looking for is a local variable or an |
7931 // argument in a context, the receiver is the global object; see | 7932 // argument in a context, the receiver is the global object; see |
7932 // ECMA-262, 3rd., 10.1.6 and 10.2.3. | 7933 // ECMA-262, 3rd., 10.1.6 and 10.2.3. |
7933 // GetElement below can cause GC. | 7934 // |
7934 Handle<JSObject> receiver( | 7935 // Use the hole as the receiver to signal that the receiver is |
7935 isolate->context()->global()->global_receiver()); | 7936 // implicit and that the global receiver should be used. |
| 7937 Handle<Object> receiver = isolate->factory()->the_hole_value(); |
7936 MaybeObject* value = (holder->IsContext()) | 7938 MaybeObject* value = (holder->IsContext()) |
7937 ? Context::cast(*holder)->get(index) | 7939 ? Context::cast(*holder)->get(index) |
7938 : JSObject::cast(*holder)->GetElement(index); | 7940 : JSObject::cast(*holder)->GetElement(index); |
7939 return MakePair(Unhole(isolate->heap(), value, attributes), *receiver); | 7941 return MakePair(Unhole(isolate->heap(), value, attributes), *receiver); |
7940 } | 7942 } |
7941 | 7943 |
7942 // If the holder is found, we read the property from it. | 7944 // If the holder is found, we read the property from it. |
7943 if (!holder.is_null() && holder->IsJSObject()) { | 7945 if (!holder.is_null() && holder->IsJSObject()) { |
7944 ASSERT(Handle<JSObject>::cast(holder)->HasProperty(*name)); | 7946 ASSERT(Handle<JSObject>::cast(holder)->HasProperty(*name)); |
7945 JSObject* object = JSObject::cast(*holder); | 7947 JSObject* object = JSObject::cast(*holder); |
7946 JSObject* receiver; | 7948 Object* receiver; |
7947 if (object->IsGlobalObject()) { | 7949 if (object->IsGlobalObject()) { |
7948 receiver = GlobalObject::cast(object)->global_receiver(); | 7950 receiver = GlobalObject::cast(object)->global_receiver(); |
7949 } else if (context->is_exception_holder(*holder)) { | 7951 } else if (context->is_exception_holder(*holder)) { |
7950 receiver = isolate->context()->global()->global_receiver(); | 7952 // Use the hole as the receiver to signal that the receiver is |
| 7953 // implicit and that the global receiver should be used. |
| 7954 receiver = isolate->heap()->the_hole_value(); |
7951 } else { | 7955 } else { |
7952 receiver = ComputeReceiverForNonGlobal(isolate, object); | 7956 receiver = ComputeReceiverForNonGlobal(isolate, object); |
7953 } | 7957 } |
7954 | 7958 |
7955 // GetProperty below can cause GC. | 7959 // GetProperty below can cause GC. |
7956 Handle<JSObject> receiver_handle(receiver); | 7960 Handle<Object> receiver_handle(receiver); |
7957 | 7961 |
7958 // No need to unhole the value here. This is taken care of by the | 7962 // No need to unhole the value here. This is taken care of by the |
7959 // GetProperty function. | 7963 // GetProperty function. |
7960 MaybeObject* value = object->GetProperty(*name); | 7964 MaybeObject* value = object->GetProperty(*name); |
7961 return MakePair(value, *receiver_handle); | 7965 return MakePair(value, *receiver_handle); |
7962 } | 7966 } |
7963 | 7967 |
7964 if (throw_error) { | 7968 if (throw_error) { |
7965 // The property doesn't exist - throw exception. | 7969 // The property doesn't exist - throw exception. |
7966 Handle<Object> reference_error = | 7970 Handle<Object> reference_error = |
7967 isolate->factory()->NewReferenceError("not_defined", | 7971 isolate->factory()->NewReferenceError("not_defined", |
7968 HandleVector(&name, 1)); | 7972 HandleVector(&name, 1)); |
7969 return MakePair(isolate->Throw(*reference_error), NULL); | 7973 return MakePair(isolate->Throw(*reference_error), NULL); |
7970 } else { | 7974 } else { |
7971 // The property doesn't exist - return undefined | 7975 // The property doesn't exist - return undefined. |
7972 return MakePair(isolate->heap()->undefined_value(), | 7976 return MakePair(isolate->heap()->undefined_value(), |
7973 isolate->heap()->undefined_value()); | 7977 isolate->heap()->undefined_value()); |
7974 } | 7978 } |
7975 } | 7979 } |
7976 | 7980 |
7977 | 7981 |
7978 RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlot) { | 7982 RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlot) { |
7979 return LoadContextSlotHelper(args, isolate, true); | 7983 return LoadContextSlotHelper(args, isolate, true); |
7980 } | 7984 } |
7981 | 7985 |
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8473 Handle<Object> reference_error = | 8477 Handle<Object> reference_error = |
8474 isolate->factory()->NewReferenceError("not_defined", | 8478 isolate->factory()->NewReferenceError("not_defined", |
8475 HandleVector(&name, 1)); | 8479 HandleVector(&name, 1)); |
8476 return MakePair(isolate->Throw(*reference_error), NULL); | 8480 return MakePair(isolate->Throw(*reference_error), NULL); |
8477 } | 8481 } |
8478 | 8482 |
8479 if (!context->IsGlobalContext()) { | 8483 if (!context->IsGlobalContext()) { |
8480 // 'eval' is not bound in the global context. Just call the function | 8484 // 'eval' is not bound in the global context. Just call the function |
8481 // with the given arguments. This is not necessarily the global eval. | 8485 // with the given arguments. This is not necessarily the global eval. |
8482 if (receiver->IsContext() || receiver->IsJSContextExtensionObject()) { | 8486 if (receiver->IsContext() || receiver->IsJSContextExtensionObject()) { |
8483 receiver = Handle<JSObject>( | 8487 receiver = isolate->factory()->the_hole_value(); |
8484 isolate->context()->global()->global_receiver(), isolate); | |
8485 } | 8488 } |
8486 return MakePair(*callee, *receiver); | 8489 return MakePair(*callee, *receiver); |
8487 } | 8490 } |
8488 | 8491 |
8489 // 'eval' is bound in the global context, but it may have been overwritten. | 8492 // 'eval' is bound in the global context, but it may have been overwritten. |
8490 // Compare it to the builtin 'GlobalEval' function to make sure. | 8493 // Compare it to the builtin 'GlobalEval' function to make sure. |
8491 if (*callee != isolate->global_context()->global_eval_fun() || | 8494 if (*callee != isolate->global_context()->global_eval_fun() || |
8492 !args[1]->IsString()) { | 8495 !args[1]->IsString()) { |
8493 return MakePair(*callee, | 8496 return MakePair(*callee, isolate->heap()->the_hole_value()); |
8494 isolate->context()->global()->global_receiver()); | |
8495 } | 8497 } |
8496 | 8498 |
8497 ASSERT(args[3]->IsSmi()); | 8499 ASSERT(args[3]->IsSmi()); |
8498 return CompileGlobalEval(isolate, | 8500 return CompileGlobalEval(isolate, |
8499 args.at<String>(1), | 8501 args.at<String>(1), |
8500 args.at<Object>(2), | 8502 args.at<Object>(2), |
8501 static_cast<StrictModeFlag>( | 8503 static_cast<StrictModeFlag>( |
8502 Smi::cast(args[3])->value())); | 8504 Smi::cast(args[3])->value())); |
8503 } | 8505 } |
8504 | 8506 |
8505 | 8507 |
8506 RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEvalNoLookup) { | 8508 RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEvalNoLookup) { |
8507 ASSERT(args.length() == 4); | 8509 ASSERT(args.length() == 4); |
8508 | 8510 |
8509 HandleScope scope(isolate); | 8511 HandleScope scope(isolate); |
8510 Handle<Object> callee = args.at<Object>(0); | 8512 Handle<Object> callee = args.at<Object>(0); |
8511 | 8513 |
8512 // 'eval' is bound in the global context, but it may have been overwritten. | 8514 // 'eval' is bound in the global context, but it may have been overwritten. |
8513 // Compare it to the builtin 'GlobalEval' function to make sure. | 8515 // Compare it to the builtin 'GlobalEval' function to make sure. |
8514 if (*callee != isolate->global_context()->global_eval_fun() || | 8516 if (*callee != isolate->global_context()->global_eval_fun() || |
8515 !args[1]->IsString()) { | 8517 !args[1]->IsString()) { |
8516 return MakePair(*callee, | 8518 return MakePair(*callee, isolate->heap()->the_hole_value()); |
8517 isolate->context()->global()->global_receiver()); | |
8518 } | 8519 } |
8519 | 8520 |
8520 ASSERT(args[3]->IsSmi()); | 8521 ASSERT(args[3]->IsSmi()); |
8521 return CompileGlobalEval(isolate, | 8522 return CompileGlobalEval(isolate, |
8522 args.at<String>(1), | 8523 args.at<String>(1), |
8523 args.at<Object>(2), | 8524 args.at<Object>(2), |
8524 static_cast<StrictModeFlag>( | 8525 static_cast<StrictModeFlag>( |
8525 Smi::cast(args[3])->value())); | 8526 Smi::cast(args[3])->value())); |
8526 } | 8527 } |
8527 | 8528 |
(...skipping 3689 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12217 } else { | 12218 } else { |
12218 // Handle last resort GC and make sure to allow future allocations | 12219 // Handle last resort GC and make sure to allow future allocations |
12219 // to grow the heap without causing GCs (if possible). | 12220 // to grow the heap without causing GCs (if possible). |
12220 isolate->counters()->gc_last_resort_from_js()->Increment(); | 12221 isolate->counters()->gc_last_resort_from_js()->Increment(); |
12221 isolate->heap()->CollectAllGarbage(false); | 12222 isolate->heap()->CollectAllGarbage(false); |
12222 } | 12223 } |
12223 } | 12224 } |
12224 | 12225 |
12225 | 12226 |
12226 } } // namespace v8::internal | 12227 } } // namespace v8::internal |
OLD | NEW |