| 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 1190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1201 ASSERT(args.length() == 2); | 1201 ASSERT(args.length() == 2); |
| 1202 CONVERT_ARG_CHECKED(JSObject, object, 0); | 1202 CONVERT_ARG_CHECKED(JSObject, object, 0); |
| 1203 CONVERT_SMI_CHECKED(properties, args[1]); | 1203 CONVERT_SMI_CHECKED(properties, args[1]); |
| 1204 if (object->HasFastProperties()) { | 1204 if (object->HasFastProperties()) { |
| 1205 NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties); | 1205 NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties); |
| 1206 } | 1206 } |
| 1207 return *object; | 1207 return *object; |
| 1208 } | 1208 } |
| 1209 | 1209 |
| 1210 | 1210 |
| 1211 static Object* Runtime_TransformToFastProperties(Arguments args) { | |
| 1212 HandleScope scope; | |
| 1213 ASSERT(args.length() == 1); | |
| 1214 CONVERT_ARG_CHECKED(JSObject, object, 0); | |
| 1215 if (!object->HasFastProperties() && !object->IsGlobalObject()) { | |
| 1216 TransformToFastProperties(object, 0); | |
| 1217 } | |
| 1218 return *object; | |
| 1219 } | |
| 1220 | |
| 1221 | |
| 1222 static Object* Runtime_RegExpExec(Arguments args) { | 1211 static Object* Runtime_RegExpExec(Arguments args) { |
| 1223 HandleScope scope; | 1212 HandleScope scope; |
| 1224 ASSERT(args.length() == 4); | 1213 ASSERT(args.length() == 4); |
| 1225 CONVERT_ARG_CHECKED(JSRegExp, regexp, 0); | 1214 CONVERT_ARG_CHECKED(JSRegExp, regexp, 0); |
| 1226 CONVERT_ARG_CHECKED(String, subject, 1); | 1215 CONVERT_ARG_CHECKED(String, subject, 1); |
| 1227 // Due to the way the JS calls are constructed this must be less than the | 1216 // Due to the way the JS calls are constructed this must be less than the |
| 1228 // length of a string, i.e. it is always a Smi. We check anyway for security. | 1217 // length of a string, i.e. it is always a Smi. We check anyway for security. |
| 1229 CONVERT_SMI_CHECKED(index, args[2]); | 1218 CONVERT_SMI_CHECKED(index, args[2]); |
| 1230 CONVERT_ARG_CHECKED(JSArray, last_match_info, 3); | 1219 CONVERT_ARG_CHECKED(JSArray, last_match_info, 3); |
| 1231 RUNTIME_ASSERT(last_match_info->HasFastElements()); | 1220 RUNTIME_ASSERT(last_match_info->HasFastElements()); |
| (...skipping 1048 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2280 schar pattern_char, | 2269 schar pattern_char, |
| 2281 int start_index) { | 2270 int start_index) { |
| 2282 for (int i = start_index, n = string.length(); i < n; i++) { | 2271 for (int i = start_index, n = string.length(); i < n; i++) { |
| 2283 if (pattern_char == string[i]) { | 2272 if (pattern_char == string[i]) { |
| 2284 return i; | 2273 return i; |
| 2285 } | 2274 } |
| 2286 } | 2275 } |
| 2287 return -1; | 2276 return -1; |
| 2288 } | 2277 } |
| 2289 | 2278 |
| 2279 |
| 2280 template <typename schar> |
| 2281 static int SingleCharLastIndexOf(Vector<const schar> string, |
| 2282 schar pattern_char, |
| 2283 int start_index) { |
| 2284 for (int i = start_index; i >= 0; i--) { |
| 2285 if (pattern_char == string[i]) { |
| 2286 return i; |
| 2287 } |
| 2288 } |
| 2289 return -1; |
| 2290 } |
| 2291 |
| 2292 |
| 2290 // Trivial string search for shorter strings. | 2293 // Trivial string search for shorter strings. |
| 2291 // On return, if "complete" is set to true, the return value is the | 2294 // On return, if "complete" is set to true, the return value is the |
| 2292 // final result of searching for the patter in the subject. | 2295 // final result of searching for the patter in the subject. |
| 2293 // If "complete" is set to false, the return value is the index where | 2296 // If "complete" is set to false, the return value is the index where |
| 2294 // further checking should start, i.e., it's guaranteed that the pattern | 2297 // further checking should start, i.e., it's guaranteed that the pattern |
| 2295 // does not occur at a position prior to the returned index. | 2298 // does not occur at a position prior to the returned index. |
| 2296 template <typename pchar, typename schar> | 2299 template <typename pchar, typename schar> |
| 2297 static int SimpleIndexOf(Vector<const schar> subject, | 2300 static int SimpleIndexOf(Vector<const schar> subject, |
| 2298 Vector<const pchar> pattern, | 2301 Vector<const pchar> pattern, |
| 2299 int idx, | 2302 int idx, |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2356 // Dispatch to different algorithms. | 2359 // Dispatch to different algorithms. |
| 2357 template <typename schar, typename pchar> | 2360 template <typename schar, typename pchar> |
| 2358 static int StringMatchStrategy(Vector<const schar> sub, | 2361 static int StringMatchStrategy(Vector<const schar> sub, |
| 2359 Vector<const pchar> pat, | 2362 Vector<const pchar> pat, |
| 2360 int start_index) { | 2363 int start_index) { |
| 2361 ASSERT(pat.length() > 1); | 2364 ASSERT(pat.length() > 1); |
| 2362 | 2365 |
| 2363 // We have an ASCII haystack and a non-ASCII needle. Check if there | 2366 // We have an ASCII haystack and a non-ASCII needle. Check if there |
| 2364 // really is a non-ASCII character in the needle and bail out if there | 2367 // really is a non-ASCII character in the needle and bail out if there |
| 2365 // is. | 2368 // is. |
| 2366 if (sizeof(pchar) > 1 && sizeof(schar) == 1) { | 2369 if (sizeof(schar) == 1 && sizeof(pchar) > 1) { |
| 2367 for (int i = 0; i < pat.length(); i++) { | 2370 for (int i = 0; i < pat.length(); i++) { |
| 2368 uc16 c = pat[i]; | 2371 uc16 c = pat[i]; |
| 2369 if (c > String::kMaxAsciiCharCode) { | 2372 if (c > String::kMaxAsciiCharCode) { |
| 2370 return -1; | 2373 return -1; |
| 2371 } | 2374 } |
| 2372 } | 2375 } |
| 2373 } | 2376 } |
| 2374 if (pat.length() < kBMMinPatternLength) { | 2377 if (pat.length() < kBMMinPatternLength) { |
| 2375 // We don't believe fancy searching can ever be more efficient. | 2378 // We don't believe fancy searching can ever be more efficient. |
| 2376 // The max shift of Boyer-Moore on a pattern of this length does | 2379 // The max shift of Boyer-Moore on a pattern of this length does |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2459 Object* index = args[2]; | 2462 Object* index = args[2]; |
| 2460 uint32_t start_index; | 2463 uint32_t start_index; |
| 2461 if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1); | 2464 if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1); |
| 2462 | 2465 |
| 2463 RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length())); | 2466 RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length())); |
| 2464 int position = Runtime::StringMatch(sub, pat, start_index); | 2467 int position = Runtime::StringMatch(sub, pat, start_index); |
| 2465 return Smi::FromInt(position); | 2468 return Smi::FromInt(position); |
| 2466 } | 2469 } |
| 2467 | 2470 |
| 2468 | 2471 |
| 2472 template <typename schar, typename pchar> |
| 2473 static int StringMatchBackwards(Vector<const schar> sub, |
| 2474 Vector<const pchar> pat, |
| 2475 int idx) { |
| 2476 ASSERT(pat.length() >= 1); |
| 2477 ASSERT(idx + pat.length() <= sub.length()); |
| 2478 |
| 2479 if (sizeof(schar) == 1 && sizeof(pchar) > 1) { |
| 2480 for (int i = 0; i < pat.length(); i++) { |
| 2481 uc16 c = pat[i]; |
| 2482 if (c > String::kMaxAsciiCharCode) { |
| 2483 return -1; |
| 2484 } |
| 2485 } |
| 2486 } |
| 2487 |
| 2488 pchar pattern_first_char = pat[0]; |
| 2489 for (int i = idx; i >= 0; i--) { |
| 2490 if (sub[i] != pattern_first_char) continue; |
| 2491 int j = 1; |
| 2492 while (j < pat.length()) { |
| 2493 if (pat[j] != sub[i+j]) { |
| 2494 break; |
| 2495 } |
| 2496 j++; |
| 2497 } |
| 2498 if (j == pat.length()) { |
| 2499 return i; |
| 2500 } |
| 2501 } |
| 2502 return -1; |
| 2503 } |
| 2504 |
| 2469 static Object* Runtime_StringLastIndexOf(Arguments args) { | 2505 static Object* Runtime_StringLastIndexOf(Arguments args) { |
| 2470 NoHandleAllocation ha; | 2506 HandleScope scope; // create a new handle scope |
| 2471 ASSERT(args.length() == 3); | 2507 ASSERT(args.length() == 3); |
| 2472 | 2508 |
| 2473 CONVERT_CHECKED(String, sub, args[0]); | 2509 CONVERT_ARG_CHECKED(String, sub, 0); |
| 2474 CONVERT_CHECKED(String, pat, args[1]); | 2510 CONVERT_ARG_CHECKED(String, pat, 1); |
| 2511 |
| 2475 Object* index = args[2]; | 2512 Object* index = args[2]; |
| 2476 | |
| 2477 sub->TryFlattenIfNotFlat(); | |
| 2478 pat->TryFlattenIfNotFlat(); | |
| 2479 | |
| 2480 uint32_t start_index; | 2513 uint32_t start_index; |
| 2481 if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1); | 2514 if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1); |
| 2482 | 2515 |
| 2483 uint32_t pattern_length = pat->length(); | 2516 uint32_t pat_length = pat->length(); |
| 2484 uint32_t sub_length = sub->length(); | 2517 uint32_t sub_length = sub->length(); |
| 2485 | 2518 |
| 2486 if (start_index + pattern_length > sub_length) { | 2519 if (start_index + pat_length > sub_length) { |
| 2487 start_index = sub_length - pattern_length; | 2520 start_index = sub_length - pat_length; |
| 2488 } | 2521 } |
| 2489 | 2522 |
| 2490 for (int i = start_index; i >= 0; i--) { | 2523 if (pat_length == 0) { |
| 2491 bool found = true; | 2524 return Smi::FromInt(start_index); |
| 2492 for (uint32_t j = 0; j < pattern_length; j++) { | |
| 2493 if (sub->Get(i + j) != pat->Get(j)) { | |
| 2494 found = false; | |
| 2495 break; | |
| 2496 } | |
| 2497 } | |
| 2498 if (found) return Smi::FromInt(i); | |
| 2499 } | 2525 } |
| 2500 | 2526 |
| 2501 return Smi::FromInt(-1); | 2527 if (!sub->IsFlat()) { |
| 2528 FlattenString(sub); |
| 2529 } |
| 2530 |
| 2531 if (pat_length == 1) { |
| 2532 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid |
| 2533 if (sub->IsAsciiRepresentation()) { |
| 2534 uc16 pchar = pat->Get(0); |
| 2535 if (pchar > String::kMaxAsciiCharCode) { |
| 2536 return Smi::FromInt(-1); |
| 2537 } |
| 2538 return Smi::FromInt(SingleCharLastIndexOf(sub->ToAsciiVector(), |
| 2539 static_cast<char>(pat->Get(0)), |
| 2540 start_index)); |
| 2541 } else { |
| 2542 return Smi::FromInt(SingleCharLastIndexOf(sub->ToUC16Vector(), |
| 2543 pat->Get(0), |
| 2544 start_index)); |
| 2545 } |
| 2546 } |
| 2547 |
| 2548 if (!pat->IsFlat()) { |
| 2549 FlattenString(pat); |
| 2550 } |
| 2551 |
| 2552 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid |
| 2553 |
| 2554 int position = -1; |
| 2555 |
| 2556 if (pat->IsAsciiRepresentation()) { |
| 2557 Vector<const char> pat_vector = pat->ToAsciiVector(); |
| 2558 if (sub->IsAsciiRepresentation()) { |
| 2559 position = StringMatchBackwards(sub->ToAsciiVector(), |
| 2560 pat_vector, |
| 2561 start_index); |
| 2562 } else { |
| 2563 position = StringMatchBackwards(sub->ToUC16Vector(), |
| 2564 pat_vector, |
| 2565 start_index); |
| 2566 } |
| 2567 } else { |
| 2568 Vector<const uc16> pat_vector = pat->ToUC16Vector(); |
| 2569 if (sub->IsAsciiRepresentation()) { |
| 2570 position = StringMatchBackwards(sub->ToAsciiVector(), |
| 2571 pat_vector, |
| 2572 start_index); |
| 2573 } else { |
| 2574 position = StringMatchBackwards(sub->ToUC16Vector(), |
| 2575 pat_vector, |
| 2576 start_index); |
| 2577 } |
| 2578 } |
| 2579 |
| 2580 return Smi::FromInt(position); |
| 2502 } | 2581 } |
| 2503 | 2582 |
| 2504 | 2583 |
| 2505 static Object* Runtime_StringLocaleCompare(Arguments args) { | 2584 static Object* Runtime_StringLocaleCompare(Arguments args) { |
| 2506 NoHandleAllocation ha; | 2585 NoHandleAllocation ha; |
| 2507 ASSERT(args.length() == 2); | 2586 ASSERT(args.length() == 2); |
| 2508 | 2587 |
| 2509 CONVERT_CHECKED(String, str1, args[0]); | 2588 CONVERT_CHECKED(String, str1, args[0]); |
| 2510 CONVERT_CHECKED(String, str2, args[1]); | 2589 CONVERT_CHECKED(String, str2, args[1]); |
| 2511 | 2590 |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2899 int unchecked = flag_attr->value(); | 2978 int unchecked = flag_attr->value(); |
| 2900 RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); | 2979 RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); |
| 2901 RUNTIME_ASSERT(!obj->IsNull()); | 2980 RUNTIME_ASSERT(!obj->IsNull()); |
| 2902 LookupResult result; | 2981 LookupResult result; |
| 2903 obj->LocalLookupRealNamedProperty(name, &result); | 2982 obj->LocalLookupRealNamedProperty(name, &result); |
| 2904 | 2983 |
| 2905 PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked); | 2984 PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked); |
| 2906 // If an existing property is either FIELD, NORMAL or CONSTANT_FUNCTION | 2985 // If an existing property is either FIELD, NORMAL or CONSTANT_FUNCTION |
| 2907 // delete it to avoid running into trouble in DefineAccessor, which | 2986 // delete it to avoid running into trouble in DefineAccessor, which |
| 2908 // handles this incorrectly if the property is readonly (does nothing) | 2987 // handles this incorrectly if the property is readonly (does nothing) |
| 2909 if (result.IsValid() && | 2988 if (result.IsProperty() && |
| 2910 (result.type() == FIELD || result.type() == NORMAL | 2989 (result.type() == FIELD || result.type() == NORMAL |
| 2911 || result.type() == CONSTANT_FUNCTION)) { | 2990 || result.type() == CONSTANT_FUNCTION)) { |
| 2912 obj->DeleteProperty(name, JSObject::NORMAL_DELETION); | 2991 obj->DeleteProperty(name, JSObject::NORMAL_DELETION); |
| 2913 } | 2992 } |
| 2914 return obj->DefineAccessor(name, flag_setter->value() == 0, fun, attr); | 2993 return obj->DefineAccessor(name, flag_setter->value() == 0, fun, attr); |
| 2915 } | 2994 } |
| 2916 | 2995 |
| 2917 static Object* Runtime_DefineOrRedefineDataProperty(Arguments args) { | 2996 static Object* Runtime_DefineOrRedefineDataProperty(Arguments args) { |
| 2918 ASSERT(args.length() == 4); | 2997 ASSERT(args.length() == 4); |
| 2919 HandleScope scope; | 2998 HandleScope scope; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2930 | 3009 |
| 2931 PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked); | 3010 PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked); |
| 2932 | 3011 |
| 2933 // Take special care when attributes are different and there is already | 3012 // Take special care when attributes are different and there is already |
| 2934 // a property. For simplicity we normalize the property which enables us | 3013 // a property. For simplicity we normalize the property which enables us |
| 2935 // to not worry about changing the instance_descriptor and creating a new | 3014 // to not worry about changing the instance_descriptor and creating a new |
| 2936 // map. The current version of SetObjectProperty does not handle attributes | 3015 // map. The current version of SetObjectProperty does not handle attributes |
| 2937 // correctly in the case where a property is a field and is reset with | 3016 // correctly in the case where a property is a field and is reset with |
| 2938 // new attributes. | 3017 // new attributes. |
| 2939 if (result.IsProperty() && attr != result.GetAttributes()) { | 3018 if (result.IsProperty() && attr != result.GetAttributes()) { |
| 2940 PropertyDetails details = PropertyDetails(attr, NORMAL); | |
| 2941 // New attributes - normalize to avoid writing to instance descriptor | 3019 // New attributes - normalize to avoid writing to instance descriptor |
| 2942 js_object->NormalizeProperties(KEEP_INOBJECT_PROPERTIES, 0); | 3020 js_object->NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| 2943 return js_object->SetNormalizedProperty(*name, *obj_value, details); | 3021 // Use IgnoreAttributes version since a readonly property may be |
| 3022 // overridden and SetProperty does not allow this. |
| 3023 return js_object->IgnoreAttributesAndSetLocalProperty(*name, |
| 3024 *obj_value, |
| 3025 attr); |
| 2944 } | 3026 } |
| 2945 | |
| 2946 return Runtime::SetObjectProperty(js_object, name, obj_value, attr); | 3027 return Runtime::SetObjectProperty(js_object, name, obj_value, attr); |
| 2947 } | 3028 } |
| 2948 | 3029 |
| 2949 | 3030 |
| 2950 Object* Runtime::SetObjectProperty(Handle<Object> object, | 3031 Object* Runtime::SetObjectProperty(Handle<Object> object, |
| 2951 Handle<Object> key, | 3032 Handle<Object> key, |
| 2952 Handle<Object> value, | 3033 Handle<Object> value, |
| 2953 PropertyAttributes attr) { | 3034 PropertyAttributes attr) { |
| 2954 HandleScope scope; | 3035 HandleScope scope; |
| 2955 | 3036 |
| 2956 if (object->IsUndefined() || object->IsNull()) { | 3037 if (object->IsUndefined() || object->IsNull()) { |
| 2957 Handle<Object> args[2] = { key, object }; | 3038 Handle<Object> args[2] = { key, object }; |
| 2958 Handle<Object> error = | 3039 Handle<Object> error = |
| 2959 Factory::NewTypeError("non_object_property_store", | 3040 Factory::NewTypeError("non_object_property_store", |
| 2960 HandleVector(args, 2)); | 3041 HandleVector(args, 2)); |
| 2961 return Top::Throw(*error); | 3042 return Top::Throw(*error); |
| 2962 } | 3043 } |
| 2963 | 3044 |
| 2964 // If the object isn't a JavaScript object, we ignore the store. | 3045 // If the object isn't a JavaScript object, we ignore the store. |
| 2965 if (!object->IsJSObject()) return *value; | 3046 if (!object->IsJSObject()) return *value; |
| 2966 | 3047 |
| 2967 Handle<JSObject> js_object = Handle<JSObject>::cast(object); | 3048 Handle<JSObject> js_object = Handle<JSObject>::cast(object); |
| 2968 | 3049 |
| 2969 // Check if the given key is an array index. | 3050 // Check if the given key is an array index. |
| 2970 uint32_t index; | 3051 uint32_t index; |
| 2971 if (Array::IndexFromObject(*key, &index)) { | 3052 if (Array::IndexFromObject(*key, &index)) { |
| 2972 ASSERT(attr == NONE); | |
| 2973 | |
| 2974 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters | 3053 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters |
| 2975 // of a string using [] notation. We need to support this too in | 3054 // of a string using [] notation. We need to support this too in |
| 2976 // JavaScript. | 3055 // JavaScript. |
| 2977 // In the case of a String object we just need to redirect the assignment to | 3056 // In the case of a String object we just need to redirect the assignment to |
| 2978 // the underlying string if the index is in range. Since the underlying | 3057 // the underlying string if the index is in range. Since the underlying |
| 2979 // string does nothing with the assignment then we can ignore such | 3058 // string does nothing with the assignment then we can ignore such |
| 2980 // assignments. | 3059 // assignments. |
| 2981 if (js_object->IsStringObjectWithCharacterAt(index)) { | 3060 if (js_object->IsStringObjectWithCharacterAt(index)) { |
| 2982 return *value; | 3061 return *value; |
| 2983 } | 3062 } |
| 2984 | 3063 |
| 2985 Handle<Object> result = SetElement(js_object, index, value); | 3064 Handle<Object> result = SetElement(js_object, index, value); |
| 2986 if (result.is_null()) return Failure::Exception(); | 3065 if (result.is_null()) return Failure::Exception(); |
| 2987 return *value; | 3066 return *value; |
| 2988 } | 3067 } |
| 2989 | 3068 |
| 2990 if (key->IsString()) { | 3069 if (key->IsString()) { |
| 2991 Handle<Object> result; | 3070 Handle<Object> result; |
| 2992 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { | 3071 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { |
| 2993 ASSERT(attr == NONE); | |
| 2994 result = SetElement(js_object, index, value); | 3072 result = SetElement(js_object, index, value); |
| 2995 } else { | 3073 } else { |
| 2996 Handle<String> key_string = Handle<String>::cast(key); | 3074 Handle<String> key_string = Handle<String>::cast(key); |
| 2997 key_string->TryFlattenIfNotFlat(); | 3075 key_string->TryFlattenIfNotFlat(); |
| 2998 result = SetProperty(js_object, key_string, value, attr); | 3076 result = SetProperty(js_object, key_string, value, attr); |
| 2999 } | 3077 } |
| 3000 if (result.is_null()) return Failure::Exception(); | 3078 if (result.is_null()) return Failure::Exception(); |
| 3001 return *value; | 3079 return *value; |
| 3002 } | 3080 } |
| 3003 | 3081 |
| 3004 // Call-back into JavaScript to convert the key to a string. | 3082 // Call-back into JavaScript to convert the key to a string. |
| 3005 bool has_pending_exception = false; | 3083 bool has_pending_exception = false; |
| 3006 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); | 3084 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); |
| 3007 if (has_pending_exception) return Failure::Exception(); | 3085 if (has_pending_exception) return Failure::Exception(); |
| 3008 Handle<String> name = Handle<String>::cast(converted); | 3086 Handle<String> name = Handle<String>::cast(converted); |
| 3009 | 3087 |
| 3010 if (name->AsArrayIndex(&index)) { | 3088 if (name->AsArrayIndex(&index)) { |
| 3011 ASSERT(attr == NONE); | |
| 3012 return js_object->SetElement(index, *value); | 3089 return js_object->SetElement(index, *value); |
| 3013 } else { | 3090 } else { |
| 3014 return js_object->SetProperty(*name, *value, attr); | 3091 return js_object->SetProperty(*name, *value, attr); |
| 3015 } | 3092 } |
| 3016 } | 3093 } |
| 3017 | 3094 |
| 3018 | 3095 |
| 3019 Object* Runtime::ForceSetObjectProperty(Handle<JSObject> js_object, | 3096 Object* Runtime::ForceSetObjectProperty(Handle<JSObject> js_object, |
| 3020 Handle<Object> key, | 3097 Handle<Object> key, |
| 3021 Handle<Object> value, | 3098 Handle<Object> value, |
| 3022 PropertyAttributes attr) { | 3099 PropertyAttributes attr) { |
| 3023 HandleScope scope; | 3100 HandleScope scope; |
| 3024 | 3101 |
| 3025 // Check if the given key is an array index. | 3102 // Check if the given key is an array index. |
| 3026 uint32_t index; | 3103 uint32_t index; |
| 3027 if (Array::IndexFromObject(*key, &index)) { | 3104 if (Array::IndexFromObject(*key, &index)) { |
| 3028 ASSERT(attr == NONE); | |
| 3029 | |
| 3030 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters | 3105 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters |
| 3031 // of a string using [] notation. We need to support this too in | 3106 // of a string using [] notation. We need to support this too in |
| 3032 // JavaScript. | 3107 // JavaScript. |
| 3033 // In the case of a String object we just need to redirect the assignment to | 3108 // In the case of a String object we just need to redirect the assignment to |
| 3034 // the underlying string if the index is in range. Since the underlying | 3109 // the underlying string if the index is in range. Since the underlying |
| 3035 // string does nothing with the assignment then we can ignore such | 3110 // string does nothing with the assignment then we can ignore such |
| 3036 // assignments. | 3111 // assignments. |
| 3037 if (js_object->IsStringObjectWithCharacterAt(index)) { | 3112 if (js_object->IsStringObjectWithCharacterAt(index)) { |
| 3038 return *value; | 3113 return *value; |
| 3039 } | 3114 } |
| 3040 | 3115 |
| 3041 return js_object->SetElement(index, *value); | 3116 return js_object->SetElement(index, *value); |
| 3042 } | 3117 } |
| 3043 | 3118 |
| 3044 if (key->IsString()) { | 3119 if (key->IsString()) { |
| 3045 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { | 3120 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { |
| 3046 ASSERT(attr == NONE); | |
| 3047 return js_object->SetElement(index, *value); | 3121 return js_object->SetElement(index, *value); |
| 3048 } else { | 3122 } else { |
| 3049 Handle<String> key_string = Handle<String>::cast(key); | 3123 Handle<String> key_string = Handle<String>::cast(key); |
| 3050 key_string->TryFlattenIfNotFlat(); | 3124 key_string->TryFlattenIfNotFlat(); |
| 3051 return js_object->IgnoreAttributesAndSetLocalProperty(*key_string, | 3125 return js_object->IgnoreAttributesAndSetLocalProperty(*key_string, |
| 3052 *value, | 3126 *value, |
| 3053 attr); | 3127 attr); |
| 3054 } | 3128 } |
| 3055 } | 3129 } |
| 3056 | 3130 |
| 3057 // Call-back into JavaScript to convert the key to a string. | 3131 // Call-back into JavaScript to convert the key to a string. |
| 3058 bool has_pending_exception = false; | 3132 bool has_pending_exception = false; |
| 3059 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); | 3133 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); |
| 3060 if (has_pending_exception) return Failure::Exception(); | 3134 if (has_pending_exception) return Failure::Exception(); |
| 3061 Handle<String> name = Handle<String>::cast(converted); | 3135 Handle<String> name = Handle<String>::cast(converted); |
| 3062 | 3136 |
| 3063 if (name->AsArrayIndex(&index)) { | 3137 if (name->AsArrayIndex(&index)) { |
| 3064 ASSERT(attr == NONE); | |
| 3065 return js_object->SetElement(index, *value); | 3138 return js_object->SetElement(index, *value); |
| 3066 } else { | 3139 } else { |
| 3067 return js_object->IgnoreAttributesAndSetLocalProperty(*name, *value, attr); | 3140 return js_object->IgnoreAttributesAndSetLocalProperty(*name, *value, attr); |
| 3068 } | 3141 } |
| 3069 } | 3142 } |
| 3070 | 3143 |
| 3071 | 3144 |
| 3072 Object* Runtime::ForceDeleteObjectProperty(Handle<JSObject> js_object, | 3145 Object* Runtime::ForceDeleteObjectProperty(Handle<JSObject> js_object, |
| 3073 Handle<Object> key) { | 3146 Handle<Object> key) { |
| 3074 HandleScope scope; | 3147 HandleScope scope; |
| (...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3513 // Handle special arguments properties. | 3586 // Handle special arguments properties. |
| 3514 if (key->Equals(Heap::length_symbol())) return Smi::FromInt(n); | 3587 if (key->Equals(Heap::length_symbol())) return Smi::FromInt(n); |
| 3515 if (key->Equals(Heap::callee_symbol())) return frame->function(); | 3588 if (key->Equals(Heap::callee_symbol())) return frame->function(); |
| 3516 | 3589 |
| 3517 // Lookup in the initial Object.prototype object. | 3590 // Lookup in the initial Object.prototype object. |
| 3518 return Top::initial_object_prototype()->GetProperty(*key); | 3591 return Top::initial_object_prototype()->GetProperty(*key); |
| 3519 } | 3592 } |
| 3520 | 3593 |
| 3521 | 3594 |
| 3522 static Object* Runtime_ToFastProperties(Arguments args) { | 3595 static Object* Runtime_ToFastProperties(Arguments args) { |
| 3596 HandleScope scope; |
| 3597 |
| 3523 ASSERT(args.length() == 1); | 3598 ASSERT(args.length() == 1); |
| 3524 Handle<Object> object = args.at<Object>(0); | 3599 Handle<Object> object = args.at<Object>(0); |
| 3525 if (object->IsJSObject()) { | 3600 if (object->IsJSObject()) { |
| 3526 Handle<JSObject> js_object = Handle<JSObject>::cast(object); | 3601 Handle<JSObject> js_object = Handle<JSObject>::cast(object); |
| 3527 js_object->TransformToFastProperties(0); | 3602 if (!js_object->HasFastProperties() && !js_object->IsGlobalObject()) { |
| 3603 js_object->TransformToFastProperties(0); |
| 3604 } |
| 3528 } | 3605 } |
| 3529 return *object; | 3606 return *object; |
| 3530 } | 3607 } |
| 3531 | 3608 |
| 3532 | 3609 |
| 3533 static Object* Runtime_ToSlowProperties(Arguments args) { | 3610 static Object* Runtime_ToSlowProperties(Arguments args) { |
| 3611 HandleScope scope; |
| 3612 |
| 3534 ASSERT(args.length() == 1); | 3613 ASSERT(args.length() == 1); |
| 3535 Handle<Object> object = args.at<Object>(0); | 3614 Handle<Object> object = args.at<Object>(0); |
| 3536 if (object->IsJSObject()) { | 3615 if (object->IsJSObject()) { |
| 3537 Handle<JSObject> js_object = Handle<JSObject>::cast(object); | 3616 Handle<JSObject> js_object = Handle<JSObject>::cast(object); |
| 3538 js_object->NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 3617 js_object->NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| 3539 } | 3618 } |
| 3540 return *object; | 3619 return *object; |
| 3541 } | 3620 } |
| 3542 | 3621 |
| 3543 | 3622 |
| (...skipping 1008 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4552 // x is (non-trivial) prefix of y: | 4631 // x is (non-trivial) prefix of y: |
| 4553 if (bufy.has_more()) return Smi::FromInt(LESS); | 4632 if (bufy.has_more()) return Smi::FromInt(LESS); |
| 4554 // y is prefix of x: | 4633 // y is prefix of x: |
| 4555 return Smi::FromInt(bufx.has_more() ? GREATER : EQUAL); | 4634 return Smi::FromInt(bufx.has_more() ? GREATER : EQUAL); |
| 4556 } | 4635 } |
| 4557 | 4636 |
| 4558 | 4637 |
| 4559 static Object* Runtime_Math_abs(Arguments args) { | 4638 static Object* Runtime_Math_abs(Arguments args) { |
| 4560 NoHandleAllocation ha; | 4639 NoHandleAllocation ha; |
| 4561 ASSERT(args.length() == 1); | 4640 ASSERT(args.length() == 1); |
| 4641 Counters::math_abs.Increment(); |
| 4562 | 4642 |
| 4563 CONVERT_DOUBLE_CHECKED(x, args[0]); | 4643 CONVERT_DOUBLE_CHECKED(x, args[0]); |
| 4564 return Heap::AllocateHeapNumber(fabs(x)); | 4644 return Heap::AllocateHeapNumber(fabs(x)); |
| 4565 } | 4645 } |
| 4566 | 4646 |
| 4567 | 4647 |
| 4568 static Object* Runtime_Math_acos(Arguments args) { | 4648 static Object* Runtime_Math_acos(Arguments args) { |
| 4569 NoHandleAllocation ha; | 4649 NoHandleAllocation ha; |
| 4570 ASSERT(args.length() == 1); | 4650 ASSERT(args.length() == 1); |
| 4651 Counters::math_acos.Increment(); |
| 4571 | 4652 |
| 4572 CONVERT_DOUBLE_CHECKED(x, args[0]); | 4653 CONVERT_DOUBLE_CHECKED(x, args[0]); |
| 4573 return TranscendentalCache::Get(TranscendentalCache::ACOS, x); | 4654 return TranscendentalCache::Get(TranscendentalCache::ACOS, x); |
| 4574 } | 4655 } |
| 4575 | 4656 |
| 4576 | 4657 |
| 4577 static Object* Runtime_Math_asin(Arguments args) { | 4658 static Object* Runtime_Math_asin(Arguments args) { |
| 4578 NoHandleAllocation ha; | 4659 NoHandleAllocation ha; |
| 4579 ASSERT(args.length() == 1); | 4660 ASSERT(args.length() == 1); |
| 4661 Counters::math_asin.Increment(); |
| 4580 | 4662 |
| 4581 CONVERT_DOUBLE_CHECKED(x, args[0]); | 4663 CONVERT_DOUBLE_CHECKED(x, args[0]); |
| 4582 return TranscendentalCache::Get(TranscendentalCache::ASIN, x); | 4664 return TranscendentalCache::Get(TranscendentalCache::ASIN, x); |
| 4583 } | 4665 } |
| 4584 | 4666 |
| 4585 | 4667 |
| 4586 static Object* Runtime_Math_atan(Arguments args) { | 4668 static Object* Runtime_Math_atan(Arguments args) { |
| 4587 NoHandleAllocation ha; | 4669 NoHandleAllocation ha; |
| 4588 ASSERT(args.length() == 1); | 4670 ASSERT(args.length() == 1); |
| 4671 Counters::math_atan.Increment(); |
| 4589 | 4672 |
| 4590 CONVERT_DOUBLE_CHECKED(x, args[0]); | 4673 CONVERT_DOUBLE_CHECKED(x, args[0]); |
| 4591 return TranscendentalCache::Get(TranscendentalCache::ATAN, x); | 4674 return TranscendentalCache::Get(TranscendentalCache::ATAN, x); |
| 4592 } | 4675 } |
| 4593 | 4676 |
| 4594 | 4677 |
| 4595 static Object* Runtime_Math_atan2(Arguments args) { | 4678 static Object* Runtime_Math_atan2(Arguments args) { |
| 4596 NoHandleAllocation ha; | 4679 NoHandleAllocation ha; |
| 4597 ASSERT(args.length() == 2); | 4680 ASSERT(args.length() == 2); |
| 4681 Counters::math_atan2.Increment(); |
| 4598 | 4682 |
| 4599 CONVERT_DOUBLE_CHECKED(x, args[0]); | 4683 CONVERT_DOUBLE_CHECKED(x, args[0]); |
| 4600 CONVERT_DOUBLE_CHECKED(y, args[1]); | 4684 CONVERT_DOUBLE_CHECKED(y, args[1]); |
| 4601 double result; | 4685 double result; |
| 4602 if (isinf(x) && isinf(y)) { | 4686 if (isinf(x) && isinf(y)) { |
| 4603 // Make sure that the result in case of two infinite arguments | 4687 // Make sure that the result in case of two infinite arguments |
| 4604 // is a multiple of Pi / 4. The sign of the result is determined | 4688 // is a multiple of Pi / 4. The sign of the result is determined |
| 4605 // by the first argument (x) and the sign of the second argument | 4689 // by the first argument (x) and the sign of the second argument |
| 4606 // determines the multiplier: one or three. | 4690 // determines the multiplier: one or three. |
| 4607 static double kPiDividedBy4 = 0.78539816339744830962; | 4691 static double kPiDividedBy4 = 0.78539816339744830962; |
| 4608 int multiplier = (x < 0) ? -1 : 1; | 4692 int multiplier = (x < 0) ? -1 : 1; |
| 4609 if (y < 0) multiplier *= 3; | 4693 if (y < 0) multiplier *= 3; |
| 4610 result = multiplier * kPiDividedBy4; | 4694 result = multiplier * kPiDividedBy4; |
| 4611 } else { | 4695 } else { |
| 4612 result = atan2(x, y); | 4696 result = atan2(x, y); |
| 4613 } | 4697 } |
| 4614 return Heap::AllocateHeapNumber(result); | 4698 return Heap::AllocateHeapNumber(result); |
| 4615 } | 4699 } |
| 4616 | 4700 |
| 4617 | 4701 |
| 4618 static Object* Runtime_Math_ceil(Arguments args) { | 4702 static Object* Runtime_Math_ceil(Arguments args) { |
| 4619 NoHandleAllocation ha; | 4703 NoHandleAllocation ha; |
| 4620 ASSERT(args.length() == 1); | 4704 ASSERT(args.length() == 1); |
| 4705 Counters::math_ceil.Increment(); |
| 4621 | 4706 |
| 4622 CONVERT_DOUBLE_CHECKED(x, args[0]); | 4707 CONVERT_DOUBLE_CHECKED(x, args[0]); |
| 4623 return Heap::NumberFromDouble(ceiling(x)); | 4708 return Heap::NumberFromDouble(ceiling(x)); |
| 4624 } | 4709 } |
| 4625 | 4710 |
| 4626 | 4711 |
| 4627 static Object* Runtime_Math_cos(Arguments args) { | 4712 static Object* Runtime_Math_cos(Arguments args) { |
| 4628 NoHandleAllocation ha; | 4713 NoHandleAllocation ha; |
| 4629 ASSERT(args.length() == 1); | 4714 ASSERT(args.length() == 1); |
| 4715 Counters::math_cos.Increment(); |
| 4630 | 4716 |
| 4631 CONVERT_DOUBLE_CHECKED(x, args[0]); | 4717 CONVERT_DOUBLE_CHECKED(x, args[0]); |
| 4632 return TranscendentalCache::Get(TranscendentalCache::COS, x); | 4718 return TranscendentalCache::Get(TranscendentalCache::COS, x); |
| 4633 } | 4719 } |
| 4634 | 4720 |
| 4635 | 4721 |
| 4636 static Object* Runtime_Math_exp(Arguments args) { | 4722 static Object* Runtime_Math_exp(Arguments args) { |
| 4637 NoHandleAllocation ha; | 4723 NoHandleAllocation ha; |
| 4638 ASSERT(args.length() == 1); | 4724 ASSERT(args.length() == 1); |
| 4725 Counters::math_exp.Increment(); |
| 4639 | 4726 |
| 4640 CONVERT_DOUBLE_CHECKED(x, args[0]); | 4727 CONVERT_DOUBLE_CHECKED(x, args[0]); |
| 4641 return TranscendentalCache::Get(TranscendentalCache::EXP, x); | 4728 return TranscendentalCache::Get(TranscendentalCache::EXP, x); |
| 4642 } | 4729 } |
| 4643 | 4730 |
| 4644 | 4731 |
| 4645 static Object* Runtime_Math_floor(Arguments args) { | 4732 static Object* Runtime_Math_floor(Arguments args) { |
| 4646 NoHandleAllocation ha; | 4733 NoHandleAllocation ha; |
| 4647 ASSERT(args.length() == 1); | 4734 ASSERT(args.length() == 1); |
| 4735 Counters::math_floor.Increment(); |
| 4648 | 4736 |
| 4649 CONVERT_DOUBLE_CHECKED(x, args[0]); | 4737 CONVERT_DOUBLE_CHECKED(x, args[0]); |
| 4650 return Heap::NumberFromDouble(floor(x)); | 4738 return Heap::NumberFromDouble(floor(x)); |
| 4651 } | 4739 } |
| 4652 | 4740 |
| 4653 | 4741 |
| 4654 static Object* Runtime_Math_log(Arguments args) { | 4742 static Object* Runtime_Math_log(Arguments args) { |
| 4655 NoHandleAllocation ha; | 4743 NoHandleAllocation ha; |
| 4656 ASSERT(args.length() == 1); | 4744 ASSERT(args.length() == 1); |
| 4745 Counters::math_log.Increment(); |
| 4657 | 4746 |
| 4658 CONVERT_DOUBLE_CHECKED(x, args[0]); | 4747 CONVERT_DOUBLE_CHECKED(x, args[0]); |
| 4659 return TranscendentalCache::Get(TranscendentalCache::LOG, x); | 4748 return TranscendentalCache::Get(TranscendentalCache::LOG, x); |
| 4660 } | 4749 } |
| 4661 | 4750 |
| 4662 | 4751 |
| 4663 // Helper function to compute x^y, where y is known to be an | 4752 // Helper function to compute x^y, where y is known to be an |
| 4664 // integer. Uses binary decomposition to limit the number of | 4753 // integer. Uses binary decomposition to limit the number of |
| 4665 // multiplications; see the discussion in "Hacker's Delight" by Henry | 4754 // multiplications; see the discussion in "Hacker's Delight" by Henry |
| 4666 // S. Warren, Jr., figure 11-6, page 213. | 4755 // S. Warren, Jr., figure 11-6, page 213. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 4687 } | 4776 } |
| 4688 } | 4777 } |
| 4689 m *= m; | 4778 m *= m; |
| 4690 } | 4779 } |
| 4691 } | 4780 } |
| 4692 | 4781 |
| 4693 | 4782 |
| 4694 static Object* Runtime_Math_pow(Arguments args) { | 4783 static Object* Runtime_Math_pow(Arguments args) { |
| 4695 NoHandleAllocation ha; | 4784 NoHandleAllocation ha; |
| 4696 ASSERT(args.length() == 2); | 4785 ASSERT(args.length() == 2); |
| 4786 Counters::math_pow.Increment(); |
| 4697 | 4787 |
| 4698 CONVERT_DOUBLE_CHECKED(x, args[0]); | 4788 CONVERT_DOUBLE_CHECKED(x, args[0]); |
| 4699 | 4789 |
| 4700 // If the second argument is a smi, it is much faster to call the | 4790 // If the second argument is a smi, it is much faster to call the |
| 4701 // custom powi() function than the generic pow(). | 4791 // custom powi() function than the generic pow(). |
| 4702 if (args[1]->IsSmi()) { | 4792 if (args[1]->IsSmi()) { |
| 4703 int y = Smi::cast(args[1])->value(); | 4793 int y = Smi::cast(args[1])->value(); |
| 4704 return Heap::AllocateHeapNumber(powi(x, y)); | 4794 return Heap::AllocateHeapNumber(powi(x, y)); |
| 4705 } | 4795 } |
| 4706 | 4796 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 4725 return Heap::nan_value(); | 4815 return Heap::nan_value(); |
| 4726 } else { | 4816 } else { |
| 4727 return Heap::AllocateHeapNumber(pow(x, y)); | 4817 return Heap::AllocateHeapNumber(pow(x, y)); |
| 4728 } | 4818 } |
| 4729 } | 4819 } |
| 4730 | 4820 |
| 4731 | 4821 |
| 4732 static Object* Runtime_Math_round(Arguments args) { | 4822 static Object* Runtime_Math_round(Arguments args) { |
| 4733 NoHandleAllocation ha; | 4823 NoHandleAllocation ha; |
| 4734 ASSERT(args.length() == 1); | 4824 ASSERT(args.length() == 1); |
| 4825 Counters::math_round.Increment(); |
| 4735 | 4826 |
| 4736 CONVERT_DOUBLE_CHECKED(x, args[0]); | 4827 CONVERT_DOUBLE_CHECKED(x, args[0]); |
| 4737 if (signbit(x) && x >= -0.5) return Heap::minus_zero_value(); | 4828 if (signbit(x) && x >= -0.5) return Heap::minus_zero_value(); |
| 4738 double integer = ceil(x); | 4829 double integer = ceil(x); |
| 4739 if (integer - x > 0.5) { integer -= 1.0; } | 4830 if (integer - x > 0.5) { integer -= 1.0; } |
| 4740 return Heap::NumberFromDouble(integer); | 4831 return Heap::NumberFromDouble(integer); |
| 4741 } | 4832 } |
| 4742 | 4833 |
| 4743 | 4834 |
| 4744 static Object* Runtime_Math_sin(Arguments args) { | 4835 static Object* Runtime_Math_sin(Arguments args) { |
| 4745 NoHandleAllocation ha; | 4836 NoHandleAllocation ha; |
| 4746 ASSERT(args.length() == 1); | 4837 ASSERT(args.length() == 1); |
| 4838 Counters::math_sin.Increment(); |
| 4747 | 4839 |
| 4748 CONVERT_DOUBLE_CHECKED(x, args[0]); | 4840 CONVERT_DOUBLE_CHECKED(x, args[0]); |
| 4749 return TranscendentalCache::Get(TranscendentalCache::SIN, x); | 4841 return TranscendentalCache::Get(TranscendentalCache::SIN, x); |
| 4750 } | 4842 } |
| 4751 | 4843 |
| 4752 | 4844 |
| 4753 static Object* Runtime_Math_sqrt(Arguments args) { | 4845 static Object* Runtime_Math_sqrt(Arguments args) { |
| 4754 NoHandleAllocation ha; | 4846 NoHandleAllocation ha; |
| 4755 ASSERT(args.length() == 1); | 4847 ASSERT(args.length() == 1); |
| 4848 Counters::math_sqrt.Increment(); |
| 4756 | 4849 |
| 4757 CONVERT_DOUBLE_CHECKED(x, args[0]); | 4850 CONVERT_DOUBLE_CHECKED(x, args[0]); |
| 4758 return Heap::AllocateHeapNumber(sqrt(x)); | 4851 return Heap::AllocateHeapNumber(sqrt(x)); |
| 4759 } | 4852 } |
| 4760 | 4853 |
| 4761 | 4854 |
| 4762 static Object* Runtime_Math_tan(Arguments args) { | 4855 static Object* Runtime_Math_tan(Arguments args) { |
| 4763 NoHandleAllocation ha; | 4856 NoHandleAllocation ha; |
| 4764 ASSERT(args.length() == 1); | 4857 ASSERT(args.length() == 1); |
| 4858 Counters::math_tan.Increment(); |
| 4765 | 4859 |
| 4766 CONVERT_DOUBLE_CHECKED(x, args[0]); | 4860 CONVERT_DOUBLE_CHECKED(x, args[0]); |
| 4767 return TranscendentalCache::Get(TranscendentalCache::TAN, x); | 4861 return TranscendentalCache::Get(TranscendentalCache::TAN, x); |
| 4768 } | 4862 } |
| 4769 | 4863 |
| 4770 | 4864 |
| 4771 // The NewArguments function is only used when constructing the | |
| 4772 // arguments array when calling non-functions from JavaScript in | |
| 4773 // runtime.js:CALL_NON_FUNCTION. | |
| 4774 static Object* Runtime_NewArguments(Arguments args) { | |
| 4775 NoHandleAllocation ha; | |
| 4776 ASSERT(args.length() == 1); | |
| 4777 | |
| 4778 // ECMA-262, 3rd., 10.1.8, p.39 | |
| 4779 CONVERT_CHECKED(JSFunction, callee, args[0]); | |
| 4780 | |
| 4781 // Compute the frame holding the arguments. | |
| 4782 JavaScriptFrameIterator it; | |
| 4783 it.AdvanceToArgumentsFrame(); | |
| 4784 JavaScriptFrame* frame = it.frame(); | |
| 4785 | |
| 4786 const int length = frame->GetProvidedParametersCount(); | |
| 4787 Object* result = Heap::AllocateArgumentsObject(callee, length); | |
| 4788 if (result->IsFailure()) return result; | |
| 4789 if (length > 0) { | |
| 4790 Object* obj = Heap::AllocateFixedArray(length); | |
| 4791 if (obj->IsFailure()) return obj; | |
| 4792 FixedArray* array = FixedArray::cast(obj); | |
| 4793 ASSERT(array->length() == length); | |
| 4794 | |
| 4795 AssertNoAllocation no_gc; | |
| 4796 WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc); | |
| 4797 for (int i = 0; i < length; i++) { | |
| 4798 array->set(i, frame->GetParameter(i), mode); | |
| 4799 } | |
| 4800 JSObject::cast(result)->set_elements(array); | |
| 4801 } | |
| 4802 return result; | |
| 4803 } | |
| 4804 | |
| 4805 | |
| 4806 static Object* Runtime_NewArgumentsFast(Arguments args) { | 4865 static Object* Runtime_NewArgumentsFast(Arguments args) { |
| 4807 NoHandleAllocation ha; | 4866 NoHandleAllocation ha; |
| 4808 ASSERT(args.length() == 3); | 4867 ASSERT(args.length() == 3); |
| 4809 | 4868 |
| 4810 JSFunction* callee = JSFunction::cast(args[0]); | 4869 JSFunction* callee = JSFunction::cast(args[0]); |
| 4811 Object** parameters = reinterpret_cast<Object**>(args[1]); | 4870 Object** parameters = reinterpret_cast<Object**>(args[1]); |
| 4812 const int length = Smi::cast(args[2])->value(); | 4871 const int length = Smi::cast(args[2])->value(); |
| 4813 | 4872 |
| 4814 Object* result = Heap::AllocateArgumentsObject(callee, length); | 4873 Object* result = Heap::AllocateArgumentsObject(callee, length); |
| 4815 if (result->IsFailure()) return result; | 4874 if (result->IsFailure()) return result; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 4842 | 4901 |
| 4843 PretenureFlag pretenure = (context->global_context() == *context) | 4902 PretenureFlag pretenure = (context->global_context() == *context) |
| 4844 ? TENURED // Allocate global closures in old space. | 4903 ? TENURED // Allocate global closures in old space. |
| 4845 : NOT_TENURED; // Allocate local closures in new space. | 4904 : NOT_TENURED; // Allocate local closures in new space. |
| 4846 Handle<JSFunction> result = | 4905 Handle<JSFunction> result = |
| 4847 Factory::NewFunctionFromBoilerplate(boilerplate, context, pretenure); | 4906 Factory::NewFunctionFromBoilerplate(boilerplate, context, pretenure); |
| 4848 return *result; | 4907 return *result; |
| 4849 } | 4908 } |
| 4850 | 4909 |
| 4851 | 4910 |
| 4852 static Code* ComputeConstructStub(Handle<SharedFunctionInfo> shared) { | 4911 static Code* ComputeConstructStub(Handle<JSFunction> function) { |
| 4853 // TODO(385): Change this to create a construct stub specialized for | 4912 Handle<Object> prototype = Factory::null_value(); |
| 4854 // the given map to make allocation of simple objects - and maybe | 4913 if (function->has_instance_prototype()) { |
| 4855 // arrays - much faster. | 4914 prototype = Handle<Object>(function->instance_prototype()); |
| 4856 if (FLAG_inline_new | 4915 } |
| 4857 && shared->has_only_simple_this_property_assignments()) { | 4916 if (function->shared()->CanGenerateInlineConstructor(*prototype)) { |
| 4858 ConstructStubCompiler compiler; | 4917 ConstructStubCompiler compiler; |
| 4859 Object* code = compiler.CompileConstructStub(*shared); | 4918 Object* code = compiler.CompileConstructStub(function->shared()); |
| 4860 if (code->IsFailure()) { | 4919 if (code->IsFailure()) { |
| 4861 return Builtins::builtin(Builtins::JSConstructStubGeneric); | 4920 return Builtins::builtin(Builtins::JSConstructStubGeneric); |
| 4862 } | 4921 } |
| 4863 return Code::cast(code); | 4922 return Code::cast(code); |
| 4864 } | 4923 } |
| 4865 | 4924 |
| 4866 return shared->construct_stub(); | 4925 return function->shared()->construct_stub(); |
| 4867 } | 4926 } |
| 4868 | 4927 |
| 4869 | 4928 |
| 4870 static Object* Runtime_NewObject(Arguments args) { | 4929 static Object* Runtime_NewObject(Arguments args) { |
| 4871 HandleScope scope; | 4930 HandleScope scope; |
| 4872 ASSERT(args.length() == 1); | 4931 ASSERT(args.length() == 1); |
| 4873 | 4932 |
| 4874 Handle<Object> constructor = args.at<Object>(0); | 4933 Handle<Object> constructor = args.at<Object>(0); |
| 4875 | 4934 |
| 4876 // If the constructor isn't a proper function we throw a type error. | 4935 // If the constructor isn't a proper function we throw a type error. |
| (...skipping 29 matching lines...) Expand all Loading... |
| 4906 } | 4965 } |
| 4907 } | 4966 } |
| 4908 | 4967 |
| 4909 // The function should be compiled for the optimization hints to be available. | 4968 // The function should be compiled for the optimization hints to be available. |
| 4910 Handle<SharedFunctionInfo> shared(function->shared()); | 4969 Handle<SharedFunctionInfo> shared(function->shared()); |
| 4911 EnsureCompiled(shared, CLEAR_EXCEPTION); | 4970 EnsureCompiled(shared, CLEAR_EXCEPTION); |
| 4912 | 4971 |
| 4913 bool first_allocation = !function->has_initial_map(); | 4972 bool first_allocation = !function->has_initial_map(); |
| 4914 Handle<JSObject> result = Factory::NewJSObject(function); | 4973 Handle<JSObject> result = Factory::NewJSObject(function); |
| 4915 if (first_allocation) { | 4974 if (first_allocation) { |
| 4916 Handle<Map> map = Handle<Map>(function->initial_map()); | |
| 4917 Handle<Code> stub = Handle<Code>( | 4975 Handle<Code> stub = Handle<Code>( |
| 4918 ComputeConstructStub(Handle<SharedFunctionInfo>(function->shared()))); | 4976 ComputeConstructStub(Handle<JSFunction>(function))); |
| 4919 function->shared()->set_construct_stub(*stub); | 4977 shared->set_construct_stub(*stub); |
| 4920 } | 4978 } |
| 4921 | 4979 |
| 4922 Counters::constructed_objects.Increment(); | 4980 Counters::constructed_objects.Increment(); |
| 4923 Counters::constructed_objects_runtime.Increment(); | 4981 Counters::constructed_objects_runtime.Increment(); |
| 4924 | 4982 |
| 4925 return *result; | 4983 return *result; |
| 4926 } | 4984 } |
| 4927 | 4985 |
| 4928 | 4986 |
| 4929 static Object* Runtime_LazyCompile(Arguments args) { | 4987 static Object* Runtime_LazyCompile(Arguments args) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 4948 // be in loops. We compile them as if they are in loops here just in case. | 5006 // be in loops. We compile them as if they are in loops here just in case. |
| 4949 ASSERT(!function->is_compiled()); | 5007 ASSERT(!function->is_compiled()); |
| 4950 if (!CompileLazyInLoop(function, Handle<Object>::null(), KEEP_EXCEPTION)) { | 5008 if (!CompileLazyInLoop(function, Handle<Object>::null(), KEEP_EXCEPTION)) { |
| 4951 return Failure::Exception(); | 5009 return Failure::Exception(); |
| 4952 } | 5010 } |
| 4953 | 5011 |
| 4954 return function->code(); | 5012 return function->code(); |
| 4955 } | 5013 } |
| 4956 | 5014 |
| 4957 | 5015 |
| 4958 static Object* Runtime_GetCalledFunction(Arguments args) { | |
| 4959 HandleScope scope; | |
| 4960 ASSERT(args.length() == 0); | |
| 4961 StackFrameIterator it; | |
| 4962 // Get past the JS-to-C exit frame. | |
| 4963 ASSERT(it.frame()->is_exit()); | |
| 4964 it.Advance(); | |
| 4965 // Get past the CALL_NON_FUNCTION activation frame. | |
| 4966 ASSERT(it.frame()->is_java_script()); | |
| 4967 it.Advance(); | |
| 4968 // Argument adaptor frames do not copy the function; we have to skip | |
| 4969 // past them to get to the real calling frame. | |
| 4970 if (it.frame()->is_arguments_adaptor()) it.Advance(); | |
| 4971 // Get the function from the top of the expression stack of the | |
| 4972 // calling frame. | |
| 4973 StandardFrame* frame = StandardFrame::cast(it.frame()); | |
| 4974 int index = frame->ComputeExpressionsCount() - 1; | |
| 4975 Object* result = frame->GetExpression(index); | |
| 4976 return result; | |
| 4977 } | |
| 4978 | |
| 4979 | |
| 4980 static Object* Runtime_GetFunctionDelegate(Arguments args) { | 5016 static Object* Runtime_GetFunctionDelegate(Arguments args) { |
| 4981 HandleScope scope; | 5017 HandleScope scope; |
| 4982 ASSERT(args.length() == 1); | 5018 ASSERT(args.length() == 1); |
| 4983 RUNTIME_ASSERT(!args[0]->IsJSFunction()); | 5019 RUNTIME_ASSERT(!args[0]->IsJSFunction()); |
| 4984 return *Execution::GetFunctionDelegate(args.at<Object>(0)); | 5020 return *Execution::GetFunctionDelegate(args.at<Object>(0)); |
| 4985 } | 5021 } |
| 4986 | 5022 |
| 4987 | 5023 |
| 4988 static Object* Runtime_GetConstructorDelegate(Arguments args) { | 5024 static Object* Runtime_GetConstructorDelegate(Arguments args) { |
| 4989 HandleScope scope; | 5025 HandleScope scope; |
| (...skipping 2984 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7974 CONVERT_CHECKED(JSFunction, f, args[0]); | 8010 CONVERT_CHECKED(JSFunction, f, args[0]); |
| 7975 return f->shared()->inferred_name(); | 8011 return f->shared()->inferred_name(); |
| 7976 } | 8012 } |
| 7977 | 8013 |
| 7978 #endif // ENABLE_DEBUGGER_SUPPORT | 8014 #endif // ENABLE_DEBUGGER_SUPPORT |
| 7979 | 8015 |
| 7980 #ifdef ENABLE_LOGGING_AND_PROFILING | 8016 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 7981 | 8017 |
| 7982 static Object* Runtime_ProfilerResume(Arguments args) { | 8018 static Object* Runtime_ProfilerResume(Arguments args) { |
| 7983 NoHandleAllocation ha; | 8019 NoHandleAllocation ha; |
| 7984 ASSERT(args.length() == 1); | 8020 ASSERT(args.length() == 2); |
| 7985 | 8021 |
| 7986 CONVERT_CHECKED(Smi, smi_modules, args[0]); | 8022 CONVERT_CHECKED(Smi, smi_modules, args[0]); |
| 7987 v8::V8::ResumeProfilerEx(smi_modules->value()); | 8023 CONVERT_CHECKED(Smi, smi_tag, args[1]); |
| 8024 v8::V8::ResumeProfilerEx(smi_modules->value(), smi_tag->value()); |
| 7988 return Heap::undefined_value(); | 8025 return Heap::undefined_value(); |
| 7989 } | 8026 } |
| 7990 | 8027 |
| 7991 | 8028 |
| 7992 static Object* Runtime_ProfilerPause(Arguments args) { | 8029 static Object* Runtime_ProfilerPause(Arguments args) { |
| 7993 NoHandleAllocation ha; | 8030 NoHandleAllocation ha; |
| 7994 ASSERT(args.length() == 1); | 8031 ASSERT(args.length() == 2); |
| 7995 | 8032 |
| 7996 CONVERT_CHECKED(Smi, smi_modules, args[0]); | 8033 CONVERT_CHECKED(Smi, smi_modules, args[0]); |
| 7997 v8::V8::PauseProfilerEx(smi_modules->value()); | 8034 CONVERT_CHECKED(Smi, smi_tag, args[1]); |
| 8035 v8::V8::PauseProfilerEx(smi_modules->value(), smi_tag->value()); |
| 7998 return Heap::undefined_value(); | 8036 return Heap::undefined_value(); |
| 7999 } | 8037 } |
| 8000 | 8038 |
| 8001 #endif // ENABLE_LOGGING_AND_PROFILING | 8039 #endif // ENABLE_LOGGING_AND_PROFILING |
| 8002 | 8040 |
| 8003 // Finds the script object from the script data. NOTE: This operation uses | 8041 // Finds the script object from the script data. NOTE: This operation uses |
| 8004 // heap traversal to find the function generated for the source position | 8042 // heap traversal to find the function generated for the source position |
| 8005 // for the requested break point. For lazily compiled functions several heap | 8043 // for the requested break point. For lazily compiled functions several heap |
| 8006 // traversals might be required rendering this operation as a rather slow | 8044 // traversals might be required rendering this operation as a rather slow |
| 8007 // operation. However for setting break points which is normally done through | 8045 // operation. However for setting break points which is normally done through |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8241 } else { | 8279 } else { |
| 8242 // Handle last resort GC and make sure to allow future allocations | 8280 // Handle last resort GC and make sure to allow future allocations |
| 8243 // to grow the heap without causing GCs (if possible). | 8281 // to grow the heap without causing GCs (if possible). |
| 8244 Counters::gc_last_resort_from_js.Increment(); | 8282 Counters::gc_last_resort_from_js.Increment(); |
| 8245 Heap::CollectAllGarbage(false); | 8283 Heap::CollectAllGarbage(false); |
| 8246 } | 8284 } |
| 8247 } | 8285 } |
| 8248 | 8286 |
| 8249 | 8287 |
| 8250 } } // namespace v8::internal | 8288 } } // namespace v8::internal |
| OLD | NEW |