Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(414)

Side by Side Diff: src/runtime.cc

Issue 844006: Merge changes up to V8 version 2.1.3 into the partial snapshots (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/partial_snapshots/
Patch Set: Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/runtime.h ('k') | src/runtime.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 20 matching lines...) Expand all
31 31
32 #include "accessors.h" 32 #include "accessors.h"
33 #include "api.h" 33 #include "api.h"
34 #include "arguments.h" 34 #include "arguments.h"
35 #include "compiler.h" 35 #include "compiler.h"
36 #include "cpu.h" 36 #include "cpu.h"
37 #include "dateparser-inl.h" 37 #include "dateparser-inl.h"
38 #include "debug.h" 38 #include "debug.h"
39 #include "execution.h" 39 #include "execution.h"
40 #include "jsregexp.h" 40 #include "jsregexp.h"
41 #include "liveedit.h"
41 #include "parser.h" 42 #include "parser.h"
42 #include "platform.h" 43 #include "platform.h"
43 #include "runtime.h" 44 #include "runtime.h"
44 #include "scopeinfo.h" 45 #include "scopeinfo.h"
45 #include "smart-pointer.h" 46 #include "smart-pointer.h"
46 #include "stub-cache.h" 47 #include "stub-cache.h"
47 #include "v8threads.h" 48 #include "v8threads.h"
48 49
49 namespace v8 { 50 namespace v8 {
50 namespace internal { 51 namespace internal {
(...skipping 1172 matching lines...) Expand 10 before | Expand all | Expand 10 after
1223 Counters::regexp_entry_runtime.Increment(); 1224 Counters::regexp_entry_runtime.Increment();
1224 Handle<Object> result = RegExpImpl::Exec(regexp, 1225 Handle<Object> result = RegExpImpl::Exec(regexp,
1225 subject, 1226 subject,
1226 index, 1227 index,
1227 last_match_info); 1228 last_match_info);
1228 if (result.is_null()) return Failure::Exception(); 1229 if (result.is_null()) return Failure::Exception();
1229 return *result; 1230 return *result;
1230 } 1231 }
1231 1232
1232 1233
1234 static Object* Runtime_FinishArrayPrototypeSetup(Arguments args) {
1235 HandleScope scope;
1236 ASSERT(args.length() == 1);
1237 CONVERT_ARG_CHECKED(JSArray, prototype, 0);
1238 // This is necessary to enable fast checks for absence of elements
1239 // on Array.prototype and below.
1240 prototype->set_elements(Heap::empty_fixed_array());
1241 return Smi::FromInt(0);
1242 }
1243
1244
1233 static Object* Runtime_MaterializeRegExpLiteral(Arguments args) { 1245 static Object* Runtime_MaterializeRegExpLiteral(Arguments args) {
1234 HandleScope scope; 1246 HandleScope scope;
1235 ASSERT(args.length() == 4); 1247 ASSERT(args.length() == 4);
1236 CONVERT_ARG_CHECKED(FixedArray, literals, 0); 1248 CONVERT_ARG_CHECKED(FixedArray, literals, 0);
1237 int index = Smi::cast(args[1])->value(); 1249 int index = Smi::cast(args[1])->value();
1238 Handle<String> pattern = args.at<String>(2); 1250 Handle<String> pattern = args.at<String>(2);
1239 Handle<String> flags = args.at<String>(3); 1251 Handle<String> flags = args.at<String>(3);
1240 1252
1241 // Get the RegExp function from the context in the literals array. 1253 // Get the RegExp function from the context in the literals array.
1242 // This is the RegExp function from the context in which the 1254 // This is the RegExp function from the context in which the
(...skipping 1358 matching lines...) Expand 10 before | Expand all | Expand 10 after
2601 } 2613 }
2602 2614
2603 int end = str1_length < str2_length ? str1_length : str2_length; 2615 int end = str1_length < str2_length ? str1_length : str2_length;
2604 2616
2605 // No need to flatten if we are going to find the answer on the first 2617 // No need to flatten if we are going to find the answer on the first
2606 // character. At this point we know there is at least one character 2618 // character. At this point we know there is at least one character
2607 // in each string, due to the trivial case handling above. 2619 // in each string, due to the trivial case handling above.
2608 int d = str1->Get(0) - str2->Get(0); 2620 int d = str1->Get(0) - str2->Get(0);
2609 if (d != 0) return Smi::FromInt(d); 2621 if (d != 0) return Smi::FromInt(d);
2610 2622
2611 str1->TryFlattenIfNotFlat(); 2623 str1->TryFlatten();
2612 str2->TryFlattenIfNotFlat(); 2624 str2->TryFlatten();
2613 2625
2614 static StringInputBuffer buf1; 2626 static StringInputBuffer buf1;
2615 static StringInputBuffer buf2; 2627 static StringInputBuffer buf2;
2616 2628
2617 buf1.Reset(str1); 2629 buf1.Reset(str1);
2618 buf2.Reset(str2); 2630 buf2.Reset(str2);
2619 2631
2620 for (int i = 0; i < end; i++) { 2632 for (int i = 0; i < end; i++) {
2621 uint16_t char1 = buf1.GetNext(); 2633 uint16_t char1 = buf1.GetNext();
2622 uint16_t char2 = buf2.GetNext(); 2634 uint16_t char2 = buf2.GetNext();
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
2811 Object* res = Heap::AllocateStringFromAscii(CStrVector(str)); 2823 Object* res = Heap::AllocateStringFromAscii(CStrVector(str));
2812 DeleteArray(str); 2824 DeleteArray(str);
2813 return res; 2825 return res;
2814 } 2826 }
2815 2827
2816 2828
2817 // Returns a single character string where first character equals 2829 // Returns a single character string where first character equals
2818 // string->Get(index). 2830 // string->Get(index).
2819 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) { 2831 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
2820 if (index < static_cast<uint32_t>(string->length())) { 2832 if (index < static_cast<uint32_t>(string->length())) {
2821 string->TryFlattenIfNotFlat(); 2833 string->TryFlatten();
2822 return LookupSingleCharacterStringFromCode( 2834 return LookupSingleCharacterStringFromCode(
2823 string->Get(index)); 2835 string->Get(index));
2824 } 2836 }
2825 return Execution::CharAt(string, index); 2837 return Execution::CharAt(string, index);
2826 } 2838 }
2827 2839
2828 2840
2829 Object* Runtime::GetElementOrCharAt(Handle<Object> object, uint32_t index) { 2841 Object* Runtime::GetElementOrCharAt(Handle<Object> object, uint32_t index) {
2830 // Handle [] indexing on Strings 2842 // Handle [] indexing on Strings
2831 if (object->IsString()) { 2843 if (object->IsString()) {
2832 Handle<Object> result = GetCharAt(Handle<String>::cast(object), index); 2844 Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
2833 if (!result->IsUndefined()) return *result; 2845 if (!result->IsUndefined()) return *result;
2834 } 2846 }
2835 2847
2836 // Handle [] indexing on String objects 2848 // Handle [] indexing on String objects
2837 if (object->IsStringObjectWithCharacterAt(index)) { 2849 if (object->IsStringObjectWithCharacterAt(index)) {
2838 Handle<JSValue> js_value = Handle<JSValue>::cast(object); 2850 Handle<JSValue> js_value = Handle<JSValue>::cast(object);
2839 Handle<Object> result = 2851 Handle<Object> result =
2840 GetCharAt(Handle<String>(String::cast(js_value->value())), index); 2852 GetCharAt(Handle<String>(String::cast(js_value->value())), index);
2841 if (!result->IsUndefined()) return *result; 2853 if (!result->IsUndefined()) return *result;
2842 } 2854 }
2843 2855
2844 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { 2856 if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
2845 Handle<Object> prototype = GetPrototype(object); 2857 Handle<Object> prototype = GetPrototype(object);
2846 return prototype->GetElement(index); 2858 return prototype->GetElement(index);
2847 } 2859 }
2848 2860
2861 return GetElement(object, index);
2862 }
2863
2864
2865 Object* Runtime::GetElement(Handle<Object> object, uint32_t index) {
2849 return object->GetElement(index); 2866 return object->GetElement(index);
2850 } 2867 }
2851 2868
2852 2869
2853 Object* Runtime::GetObjectProperty(Handle<Object> object, Handle<Object> key) { 2870 Object* Runtime::GetObjectProperty(Handle<Object> object, Handle<Object> key) {
2854 HandleScope scope; 2871 HandleScope scope;
2855 2872
2856 if (object->IsUndefined() || object->IsNull()) { 2873 if (object->IsUndefined() || object->IsNull()) {
2857 Handle<Object> args[2] = { key, object }; 2874 Handle<Object> args[2] = { key, object };
2858 Handle<Object> error = 2875 Handle<Object> error =
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
3065 if (result.is_null()) return Failure::Exception(); 3082 if (result.is_null()) return Failure::Exception();
3066 return *value; 3083 return *value;
3067 } 3084 }
3068 3085
3069 if (key->IsString()) { 3086 if (key->IsString()) {
3070 Handle<Object> result; 3087 Handle<Object> result;
3071 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { 3088 if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
3072 result = SetElement(js_object, index, value); 3089 result = SetElement(js_object, index, value);
3073 } else { 3090 } else {
3074 Handle<String> key_string = Handle<String>::cast(key); 3091 Handle<String> key_string = Handle<String>::cast(key);
3075 key_string->TryFlattenIfNotFlat(); 3092 key_string->TryFlatten();
3076 result = SetProperty(js_object, key_string, value, attr); 3093 result = SetProperty(js_object, key_string, value, attr);
3077 } 3094 }
3078 if (result.is_null()) return Failure::Exception(); 3095 if (result.is_null()) return Failure::Exception();
3079 return *value; 3096 return *value;
3080 } 3097 }
3081 3098
3082 // Call-back into JavaScript to convert the key to a string. 3099 // Call-back into JavaScript to convert the key to a string.
3083 bool has_pending_exception = false; 3100 bool has_pending_exception = false;
3084 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); 3101 Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
3085 if (has_pending_exception) return Failure::Exception(); 3102 if (has_pending_exception) return Failure::Exception();
(...skipping 28 matching lines...) Expand all
3114 } 3131 }
3115 3132
3116 return js_object->SetElement(index, *value); 3133 return js_object->SetElement(index, *value);
3117 } 3134 }
3118 3135
3119 if (key->IsString()) { 3136 if (key->IsString()) {
3120 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { 3137 if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
3121 return js_object->SetElement(index, *value); 3138 return js_object->SetElement(index, *value);
3122 } else { 3139 } else {
3123 Handle<String> key_string = Handle<String>::cast(key); 3140 Handle<String> key_string = Handle<String>::cast(key);
3124 key_string->TryFlattenIfNotFlat(); 3141 key_string->TryFlatten();
3125 return js_object->IgnoreAttributesAndSetLocalProperty(*key_string, 3142 return js_object->IgnoreAttributesAndSetLocalProperty(*key_string,
3126 *value, 3143 *value,
3127 attr); 3144 attr);
3128 } 3145 }
3129 } 3146 }
3130 3147
3131 // Call-back into JavaScript to convert the key to a string. 3148 // Call-back into JavaScript to convert the key to a string.
3132 bool has_pending_exception = false; 3149 bool has_pending_exception = false;
3133 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); 3150 Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
3134 if (has_pending_exception) return Failure::Exception(); 3151 if (has_pending_exception) return Failure::Exception();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
3166 if (key->IsString()) { 3183 if (key->IsString()) {
3167 key_string = Handle<String>::cast(key); 3184 key_string = Handle<String>::cast(key);
3168 } else { 3185 } else {
3169 // Call-back into JavaScript to convert the key to a string. 3186 // Call-back into JavaScript to convert the key to a string.
3170 bool has_pending_exception = false; 3187 bool has_pending_exception = false;
3171 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); 3188 Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
3172 if (has_pending_exception) return Failure::Exception(); 3189 if (has_pending_exception) return Failure::Exception();
3173 key_string = Handle<String>::cast(converted); 3190 key_string = Handle<String>::cast(converted);
3174 } 3191 }
3175 3192
3176 key_string->TryFlattenIfNotFlat(); 3193 key_string->TryFlatten();
3177 return js_object->DeleteProperty(*key_string, JSObject::FORCE_DELETION); 3194 return js_object->DeleteProperty(*key_string, JSObject::FORCE_DELETION);
3178 } 3195 }
3179 3196
3180 3197
3181 static Object* Runtime_SetProperty(Arguments args) { 3198 static Object* Runtime_SetProperty(Arguments args) {
3182 NoHandleAllocation ha; 3199 NoHandleAllocation ha;
3183 RUNTIME_ASSERT(args.length() == 3 || args.length() == 4); 3200 RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
3184 3201
3185 Handle<Object> object = args.at<Object>(0); 3202 Handle<Object> object = args.at<Object>(0);
3186 Handle<Object> key = args.at<Object>(1); 3203 Handle<Object> key = args.at<Object>(1);
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after
3662 // host objects gives that it is okay to return "object" 3679 // host objects gives that it is okay to return "object"
3663 return Heap::object_symbol(); 3680 return Heap::object_symbol();
3664 } 3681 }
3665 } 3682 }
3666 3683
3667 3684
3668 static Object* Runtime_StringToNumber(Arguments args) { 3685 static Object* Runtime_StringToNumber(Arguments args) {
3669 NoHandleAllocation ha; 3686 NoHandleAllocation ha;
3670 ASSERT(args.length() == 1); 3687 ASSERT(args.length() == 1);
3671 CONVERT_CHECKED(String, subject, args[0]); 3688 CONVERT_CHECKED(String, subject, args[0]);
3672 subject->TryFlattenIfNotFlat(); 3689 subject->TryFlatten();
3673 return Heap::NumberFromDouble(StringToDouble(subject, ALLOW_HEX)); 3690 return Heap::NumberFromDouble(StringToDouble(subject, ALLOW_HEX));
3674 } 3691 }
3675 3692
3676 3693
3677 static Object* Runtime_StringFromCharCodeArray(Arguments args) { 3694 static Object* Runtime_StringFromCharCodeArray(Arguments args) {
3678 NoHandleAllocation ha; 3695 NoHandleAllocation ha;
3679 ASSERT(args.length() == 1); 3696 ASSERT(args.length() == 1);
3680 3697
3681 CONVERT_CHECKED(JSArray, codes, args[0]); 3698 CONVERT_CHECKED(JSArray, codes, args[0]);
3682 int length = Smi::cast(codes->length())->value(); 3699 int length = Smi::cast(codes->length())->value();
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
3744 return kNotEscaped[character] != 0; 3761 return kNotEscaped[character] != 0;
3745 } 3762 }
3746 3763
3747 3764
3748 static Object* Runtime_URIEscape(Arguments args) { 3765 static Object* Runtime_URIEscape(Arguments args) {
3749 const char hex_chars[] = "0123456789ABCDEF"; 3766 const char hex_chars[] = "0123456789ABCDEF";
3750 NoHandleAllocation ha; 3767 NoHandleAllocation ha;
3751 ASSERT(args.length() == 1); 3768 ASSERT(args.length() == 1);
3752 CONVERT_CHECKED(String, source, args[0]); 3769 CONVERT_CHECKED(String, source, args[0]);
3753 3770
3754 source->TryFlattenIfNotFlat(); 3771 source->TryFlatten();
3755 3772
3756 int escaped_length = 0; 3773 int escaped_length = 0;
3757 int length = source->length(); 3774 int length = source->length();
3758 { 3775 {
3759 Access<StringInputBuffer> buffer(&runtime_string_input_buffer); 3776 Access<StringInputBuffer> buffer(&runtime_string_input_buffer);
3760 buffer->Reset(source); 3777 buffer->Reset(source);
3761 while (buffer->has_more()) { 3778 while (buffer->has_more()) {
3762 uint16_t character = buffer->GetNext(); 3779 uint16_t character = buffer->GetNext();
3763 if (character >= 256) { 3780 if (character >= 256) {
3764 escaped_length += 6; 3781 escaped_length += 6;
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
3857 return character; 3874 return character;
3858 } 3875 }
3859 } 3876 }
3860 3877
3861 3878
3862 static Object* Runtime_URIUnescape(Arguments args) { 3879 static Object* Runtime_URIUnescape(Arguments args) {
3863 NoHandleAllocation ha; 3880 NoHandleAllocation ha;
3864 ASSERT(args.length() == 1); 3881 ASSERT(args.length() == 1);
3865 CONVERT_CHECKED(String, source, args[0]); 3882 CONVERT_CHECKED(String, source, args[0]);
3866 3883
3867 source->TryFlattenIfNotFlat(); 3884 source->TryFlatten();
3868 3885
3869 bool ascii = true; 3886 bool ascii = true;
3870 int length = source->length(); 3887 int length = source->length();
3871 3888
3872 int unescaped_length = 0; 3889 int unescaped_length = 0;
3873 for (int i = 0; i < length; unescaped_length++) { 3890 for (int i = 0; i < length; unescaped_length++) {
3874 int step; 3891 int step;
3875 if (Unescape(source, i, length, &step) > String::kMaxAsciiCharCode) { 3892 if (Unescape(source, i, length, &step) > String::kMaxAsciiCharCode) {
3876 ascii = false; 3893 ascii = false;
3877 } 3894 }
(...skipping 19 matching lines...) Expand all
3897 return destination; 3914 return destination;
3898 } 3915 }
3899 3916
3900 3917
3901 static Object* Runtime_StringParseInt(Arguments args) { 3918 static Object* Runtime_StringParseInt(Arguments args) {
3902 NoHandleAllocation ha; 3919 NoHandleAllocation ha;
3903 3920
3904 CONVERT_CHECKED(String, s, args[0]); 3921 CONVERT_CHECKED(String, s, args[0]);
3905 CONVERT_SMI_CHECKED(radix, args[1]); 3922 CONVERT_SMI_CHECKED(radix, args[1]);
3906 3923
3907 s->TryFlattenIfNotFlat(); 3924 s->TryFlatten();
3908 3925
3909 int len = s->length(); 3926 int len = s->length();
3910 int i; 3927 int i;
3911 3928
3912 // Skip leading white space. 3929 // Skip leading white space.
3913 for (i = 0; i < len && Scanner::kIsWhiteSpace.get(s->Get(i)); i++) ; 3930 for (i = 0; i < len && Scanner::kIsWhiteSpace.get(s->Get(i)); i++) ;
3914 if (i == len) return Heap::nan_value(); 3931 if (i == len) return Heap::nan_value();
3915 3932
3916 // Compute the sign (default to +). 3933 // Compute the sign (default to +).
3917 int sign = 1; 3934 int sign = 1;
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
4061 } else { 4078 } else {
4062 // If we didn't actually change anything in doing the conversion 4079 // If we didn't actually change anything in doing the conversion
4063 // we simple return the result and let the converted string 4080 // we simple return the result and let the converted string
4064 // become garbage; there is no reason to keep two identical strings 4081 // become garbage; there is no reason to keep two identical strings
4065 // alive. 4082 // alive.
4066 return s; 4083 return s;
4067 } 4084 }
4068 } 4085 }
4069 4086
4070 4087
4071 template <class Converter> 4088 static inline SeqAsciiString* TryGetSeqAsciiString(String* s) {
4072 static Object* ConvertCase(Arguments args, 4089 if (!s->IsFlat() || !s->IsAsciiRepresentation()) return NULL;
4073 unibrow::Mapping<Converter, 128>* mapping) { 4090 if (s->IsConsString()) {
4091 ASSERT(ConsString::cast(s)->second()->length() == 0);
4092 return SeqAsciiString::cast(ConsString::cast(s)->first());
4093 }
4094 return SeqAsciiString::cast(s);
4095 }
4096
4097
4098 namespace {
4099
4100 struct ToLowerTraits {
4101 typedef unibrow::ToLowercase UnibrowConverter;
4102
4103 static bool ConvertAscii(char* dst, char* src, int length) {
4104 bool changed = false;
4105 for (int i = 0; i < length; ++i) {
4106 char c = src[i];
4107 if ('A' <= c && c <= 'Z') {
4108 c += ('a' - 'A');
4109 changed = true;
4110 }
4111 dst[i] = c;
4112 }
4113 return changed;
4114 }
4115 };
4116
4117
4118 struct ToUpperTraits {
4119 typedef unibrow::ToUppercase UnibrowConverter;
4120
4121 static bool ConvertAscii(char* dst, char* src, int length) {
4122 bool changed = false;
4123 for (int i = 0; i < length; ++i) {
4124 char c = src[i];
4125 if ('a' <= c && c <= 'z') {
4126 c -= ('a' - 'A');
4127 changed = true;
4128 }
4129 dst[i] = c;
4130 }
4131 return changed;
4132 }
4133 };
4134
4135 } // namespace
4136
4137
4138 template <typename ConvertTraits>
4139 static Object* ConvertCase(
4140 Arguments args,
4141 unibrow::Mapping<typename ConvertTraits::UnibrowConverter, 128>* mapping) {
4074 NoHandleAllocation ha; 4142 NoHandleAllocation ha;
4143 CONVERT_CHECKED(String, s, args[0]);
4144 s->TryFlatten();
4075 4145
4076 CONVERT_CHECKED(String, s, args[0]); 4146 const int length = s->length();
4077 s->TryFlattenIfNotFlat(); 4147 // Assume that the string is not empty; we need this assumption later
4148 if (length == 0) return s;
4078 4149
4079 int input_string_length = s->length(); 4150 // Simpler handling of ascii strings.
4080 // Assume that the string is not empty; we need this assumption later 4151 //
4081 if (input_string_length == 0) return s; 4152 // NOTE: This assumes that the upper/lower case of an ascii
4082 int length = input_string_length; 4153 // character is also ascii. This is currently the case, but it
4154 // might break in the future if we implement more context and locale
4155 // dependent upper/lower conversions.
4156 SeqAsciiString* seq_ascii = TryGetSeqAsciiString(s);
4157 if (seq_ascii != NULL) {
4158 Object* o = Heap::AllocateRawAsciiString(length);
4159 if (o->IsFailure()) return o;
4160 SeqAsciiString* result = SeqAsciiString::cast(o);
4161 bool has_changed_character = ConvertTraits::ConvertAscii(
4162 result->GetChars(), seq_ascii->GetChars(), length);
4163 return has_changed_character ? result : s;
4164 }
4083 4165
4084 Object* answer = ConvertCaseHelper(s, length, length, mapping); 4166 Object* answer = ConvertCaseHelper(s, length, length, mapping);
4085 if (answer->IsSmi()) { 4167 if (answer->IsSmi()) {
4086 // Retry with correct length. 4168 // Retry with correct length.
4087 answer = ConvertCaseHelper(s, Smi::cast(answer)->value(), length, mapping); 4169 answer = ConvertCaseHelper(s, Smi::cast(answer)->value(), length, mapping);
4088 } 4170 }
4089 return answer; // This may be a failure. 4171 return answer; // This may be a failure.
4090 } 4172 }
4091 4173
4092 4174
4093 static Object* Runtime_StringToLowerCase(Arguments args) { 4175 static Object* Runtime_StringToLowerCase(Arguments args) {
4094 return ConvertCase<unibrow::ToLowercase>(args, &to_lower_mapping); 4176 return ConvertCase<ToLowerTraits>(args, &to_lower_mapping);
4095 } 4177 }
4096 4178
4097 4179
4098 static Object* Runtime_StringToUpperCase(Arguments args) { 4180 static Object* Runtime_StringToUpperCase(Arguments args) {
4099 return ConvertCase<unibrow::ToUppercase>(args, &to_upper_mapping); 4181 return ConvertCase<ToUpperTraits>(args, &to_upper_mapping);
4100 } 4182 }
4101 4183
4184
4102 static inline bool IsTrimWhiteSpace(unibrow::uchar c) { 4185 static inline bool IsTrimWhiteSpace(unibrow::uchar c) {
4103 return unibrow::WhiteSpace::Is(c) || c == 0x200b; 4186 return unibrow::WhiteSpace::Is(c) || c == 0x200b;
4104 } 4187 }
4105 4188
4189
4106 static Object* Runtime_StringTrim(Arguments args) { 4190 static Object* Runtime_StringTrim(Arguments args) {
4107 NoHandleAllocation ha; 4191 NoHandleAllocation ha;
4108 ASSERT(args.length() == 3); 4192 ASSERT(args.length() == 3);
4109 4193
4110 CONVERT_CHECKED(String, s, args[0]); 4194 CONVERT_CHECKED(String, s, args[0]);
4111 CONVERT_BOOLEAN_CHECKED(trimLeft, args[1]); 4195 CONVERT_BOOLEAN_CHECKED(trimLeft, args[1]);
4112 CONVERT_BOOLEAN_CHECKED(trimRight, args[2]); 4196 CONVERT_BOOLEAN_CHECKED(trimRight, args[2]);
4113 4197
4114 s->TryFlattenIfNotFlat(); 4198 s->TryFlatten();
4115 int length = s->length(); 4199 int length = s->length();
4116 4200
4117 int left = 0; 4201 int left = 0;
4118 if (trimLeft) { 4202 if (trimLeft) {
4119 while (left < length && IsTrimWhiteSpace(s->Get(left))) { 4203 while (left < length && IsTrimWhiteSpace(s->Get(left))) {
4120 left++; 4204 left++;
4121 } 4205 }
4122 } 4206 }
4123 4207
4124 int right = length; 4208 int right = length;
4125 if (trimRight) { 4209 if (trimRight) {
4126 while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) { 4210 while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) {
4127 right--; 4211 right--;
4128 } 4212 }
4129 } 4213 }
4130 return s->SubString(left, right); 4214 return s->SubString(left, right);
4131 } 4215 }
4132 4216
4217
4218 // Copies ascii characters to the given fixed array looking up
4219 // one-char strings in the cache. Gives up on the first char that is
4220 // not in the cache and fills the remainder with smi zeros. Returns
4221 // the length of the successfully copied prefix.
4222 static int CopyCachedAsciiCharsToArray(const char* chars,
4223 FixedArray* elements,
4224 int length) {
4225 AssertNoAllocation nogc;
4226 FixedArray* ascii_cache = Heap::single_character_string_cache();
4227 Object* undefined = Heap::undefined_value();
4228 int i;
4229 for (i = 0; i < length; ++i) {
4230 Object* value = ascii_cache->get(chars[i]);
4231 if (value == undefined) break;
4232 ASSERT(!Heap::InNewSpace(value));
4233 elements->set(i, value, SKIP_WRITE_BARRIER);
4234 }
4235 if (i < length) {
4236 ASSERT(Smi::FromInt(0) == 0);
4237 memset(elements->data_start() + i, 0, kPointerSize * (length - i));
4238 }
4239 #ifdef DEBUG
4240 for (int j = 0; j < length; ++j) {
4241 Object* element = elements->get(j);
4242 ASSERT(element == Smi::FromInt(0) ||
4243 (element->IsString() && String::cast(element)->LooksValid()));
4244 }
4245 #endif
4246 return i;
4247 }
4248
4249
4250 // Converts a String to JSArray.
4251 // For example, "foo" => ["f", "o", "o"].
4252 static Object* Runtime_StringToArray(Arguments args) {
4253 HandleScope scope;
4254 ASSERT(args.length() == 1);
4255 CONVERT_ARG_CHECKED(String, s, 0);
4256
4257 s->TryFlatten();
4258 const int length = s->length();
4259
4260 Handle<FixedArray> elements;
4261 if (s->IsFlat() && s->IsAsciiRepresentation()) {
4262 Object* obj = Heap::AllocateUninitializedFixedArray(length);
4263 if (obj->IsFailure()) return obj;
4264 elements = Handle<FixedArray>(FixedArray::cast(obj));
4265
4266 Vector<const char> chars = s->ToAsciiVector();
4267 // Note, this will initialize all elements (not only the prefix)
4268 // to prevent GC from seeing partially initialized array.
4269 int num_copied_from_cache = CopyCachedAsciiCharsToArray(chars.start(),
4270 *elements,
4271 length);
4272
4273 for (int i = num_copied_from_cache; i < length; ++i) {
4274 elements->set(i, *LookupSingleCharacterStringFromCode(chars[i]));
4275 }
4276 } else {
4277 elements = Factory::NewFixedArray(length);
4278 for (int i = 0; i < length; ++i) {
4279 elements->set(i, *LookupSingleCharacterStringFromCode(s->Get(i)));
4280 }
4281 }
4282
4283 #ifdef DEBUG
4284 for (int i = 0; i < length; ++i) {
4285 ASSERT(String::cast(elements->get(i))->length() == 1);
4286 }
4287 #endif
4288
4289 return *Factory::NewJSArrayWithElements(elements);
4290 }
4291
4292
4133 bool Runtime::IsUpperCaseChar(uint16_t ch) { 4293 bool Runtime::IsUpperCaseChar(uint16_t ch) {
4134 unibrow::uchar chars[unibrow::ToUppercase::kMaxWidth]; 4294 unibrow::uchar chars[unibrow::ToUppercase::kMaxWidth];
4135 int char_length = to_upper_mapping.get(ch, 0, chars); 4295 int char_length = to_upper_mapping.get(ch, 0, chars);
4136 return char_length == 0; 4296 return char_length == 0;
4137 } 4297 }
4138 4298
4139 4299
4140 static Object* Runtime_NumberToString(Arguments args) { 4300 static Object* Runtime_NumberToString(Arguments args) {
4141 NoHandleAllocation ha; 4301 NoHandleAllocation ha;
4142 ASSERT(args.length() == 1); 4302 ASSERT(args.length() == 1);
4143 4303
4144 Object* number = args[0]; 4304 Object* number = args[0];
4145 RUNTIME_ASSERT(number->IsNumber()); 4305 RUNTIME_ASSERT(number->IsNumber());
4146 4306
4147 return Heap::NumberToString(number); 4307 return Heap::NumberToString(number);
4148 } 4308 }
4149 4309
4150 4310
4151 static Object* Runtime_NumberToInteger(Arguments args) { 4311 static Object* Runtime_NumberToInteger(Arguments args) {
4152 NoHandleAllocation ha; 4312 NoHandleAllocation ha;
4153 ASSERT(args.length() == 1); 4313 ASSERT(args.length() == 1);
4154 4314
4155 Object* obj = args[0]; 4315 CONVERT_DOUBLE_CHECKED(number, args[0]);
4156 if (obj->IsSmi()) return obj; 4316
4157 CONVERT_DOUBLE_CHECKED(number, obj); 4317 // We do not include 0 so that we don't have to treat +0 / -0 cases.
4318 if (number > 0 && number <= Smi::kMaxValue) {
4319 return Smi::FromInt(static_cast<int>(number));
4320 }
4158 return Heap::NumberFromDouble(DoubleToInteger(number)); 4321 return Heap::NumberFromDouble(DoubleToInteger(number));
4159 } 4322 }
4160 4323
4161 4324
4162 static Object* Runtime_NumberToJSUint32(Arguments args) { 4325 static Object* Runtime_NumberToJSUint32(Arguments args) {
4163 NoHandleAllocation ha; 4326 NoHandleAllocation ha;
4164 ASSERT(args.length() == 1); 4327 ASSERT(args.length() == 1);
4165 4328
4166 Object* obj = args[0]; 4329 CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, args[0]);
4167 if (obj->IsSmi() && Smi::cast(obj)->value() >= 0) return obj;
4168 CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, obj);
4169 return Heap::NumberFromUint32(number); 4330 return Heap::NumberFromUint32(number);
4170 } 4331 }
4171 4332
4172 4333
4173 static Object* Runtime_NumberToJSInt32(Arguments args) { 4334 static Object* Runtime_NumberToJSInt32(Arguments args) {
4174 NoHandleAllocation ha; 4335 NoHandleAllocation ha;
4175 ASSERT(args.length() == 1); 4336 ASSERT(args.length() == 1);
4176 4337
4177 Object* obj = args[0]; 4338 CONVERT_DOUBLE_CHECKED(number, args[0]);
4178 if (obj->IsSmi()) return obj; 4339
4179 CONVERT_DOUBLE_CHECKED(number, obj); 4340 // We do not include 0 so that we don't have to treat +0 / -0 cases.
4341 if (number > 0 && number <= Smi::kMaxValue) {
4342 return Smi::FromInt(static_cast<int>(number));
4343 }
4180 return Heap::NumberFromInt32(DoubleToInt32(number)); 4344 return Heap::NumberFromInt32(DoubleToInt32(number));
4181 } 4345 }
4182 4346
4183 4347
4184 // Converts a Number to a Smi, if possible. Returns NaN if the number is not 4348 // Converts a Number to a Smi, if possible. Returns NaN if the number is not
4185 // a small integer. 4349 // a small integer.
4186 static Object* Runtime_NumberToSmi(Arguments args) { 4350 static Object* Runtime_NumberToSmi(Arguments args) {
4187 NoHandleAllocation ha; 4351 NoHandleAllocation ha;
4188 ASSERT(args.length() == 1); 4352 ASSERT(args.length() == 1);
4189 4353
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after
4586 if (diff != 0) return Smi::FromInt(diff); 4750 if (diff != 0) return Smi::FromInt(diff);
4587 } 4751 }
4588 4752
4589 // If one array is a suffix of the other array, the longest array is 4753 // If one array is a suffix of the other array, the longest array is
4590 // the representation of the largest of the Smis in the 4754 // the representation of the largest of the Smis in the
4591 // lexicographic ordering. 4755 // lexicographic ordering.
4592 return Smi::FromInt(x_index - y_index); 4756 return Smi::FromInt(x_index - y_index);
4593 } 4757 }
4594 4758
4595 4759
4760 static Object* StringInputBufferCompare(String* x, String* y) {
4761 static StringInputBuffer bufx;
4762 static StringInputBuffer bufy;
4763 bufx.Reset(x);
4764 bufy.Reset(y);
4765 while (bufx.has_more() && bufy.has_more()) {
4766 int d = bufx.GetNext() - bufy.GetNext();
4767 if (d < 0) return Smi::FromInt(LESS);
4768 else if (d > 0) return Smi::FromInt(GREATER);
4769 }
4770
4771 // x is (non-trivial) prefix of y:
4772 if (bufy.has_more()) return Smi::FromInt(LESS);
4773 // y is prefix of x:
4774 return Smi::FromInt(bufx.has_more() ? GREATER : EQUAL);
4775 }
4776
4777
4778 static Object* FlatStringCompare(String* x, String* y) {
4779 ASSERT(x->IsFlat());
4780 ASSERT(y->IsFlat());
4781 Object* equal_prefix_result = Smi::FromInt(EQUAL);
4782 int prefix_length = x->length();
4783 if (y->length() < prefix_length) {
4784 prefix_length = y->length();
4785 equal_prefix_result = Smi::FromInt(GREATER);
4786 } else if (y->length() > prefix_length) {
4787 equal_prefix_result = Smi::FromInt(LESS);
4788 }
4789 int r;
4790 if (x->IsAsciiRepresentation()) {
4791 Vector<const char> x_chars = x->ToAsciiVector();
4792 if (y->IsAsciiRepresentation()) {
4793 Vector<const char> y_chars = y->ToAsciiVector();
4794 r = memcmp(x_chars.start(), y_chars.start(), prefix_length);
4795 } else {
4796 Vector<const uc16> y_chars = y->ToUC16Vector();
4797 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
4798 }
4799 } else {
4800 Vector<const uc16> x_chars = x->ToUC16Vector();
4801 if (y->IsAsciiRepresentation()) {
4802 Vector<const char> y_chars = y->ToAsciiVector();
4803 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
4804 } else {
4805 Vector<const uc16> y_chars = y->ToUC16Vector();
4806 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
4807 }
4808 }
4809 Object* result;
4810 if (r == 0) {
4811 result = equal_prefix_result;
4812 } else {
4813 result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
4814 }
4815 ASSERT(result == StringInputBufferCompare(x, y));
4816 return result;
4817 }
4818
4819
4596 static Object* Runtime_StringCompare(Arguments args) { 4820 static Object* Runtime_StringCompare(Arguments args) {
4597 NoHandleAllocation ha; 4821 NoHandleAllocation ha;
4598 ASSERT(args.length() == 2); 4822 ASSERT(args.length() == 2);
4599 4823
4600 CONVERT_CHECKED(String, x, args[0]); 4824 CONVERT_CHECKED(String, x, args[0]);
4601 CONVERT_CHECKED(String, y, args[1]); 4825 CONVERT_CHECKED(String, y, args[1]);
4602 4826
4603 Counters::string_compare_runtime.Increment(); 4827 Counters::string_compare_runtime.Increment();
4604 4828
4605 // A few fast case tests before we flatten. 4829 // A few fast case tests before we flatten.
4606 if (x == y) return Smi::FromInt(EQUAL); 4830 if (x == y) return Smi::FromInt(EQUAL);
4607 if (y->length() == 0) { 4831 if (y->length() == 0) {
4608 if (x->length() == 0) return Smi::FromInt(EQUAL); 4832 if (x->length() == 0) return Smi::FromInt(EQUAL);
4609 return Smi::FromInt(GREATER); 4833 return Smi::FromInt(GREATER);
4610 } else if (x->length() == 0) { 4834 } else if (x->length() == 0) {
4611 return Smi::FromInt(LESS); 4835 return Smi::FromInt(LESS);
4612 } 4836 }
4613 4837
4614 int d = x->Get(0) - y->Get(0); 4838 int d = x->Get(0) - y->Get(0);
4615 if (d < 0) return Smi::FromInt(LESS); 4839 if (d < 0) return Smi::FromInt(LESS);
4616 else if (d > 0) return Smi::FromInt(GREATER); 4840 else if (d > 0) return Smi::FromInt(GREATER);
4617 4841
4618 x->TryFlattenIfNotFlat(); 4842 x->TryFlatten();
4619 y->TryFlattenIfNotFlat(); 4843 y->TryFlatten();
4620 4844
4621 static StringInputBuffer bufx; 4845 return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
4622 static StringInputBuffer bufy; 4846 : StringInputBufferCompare(x, y);
4623 bufx.Reset(x);
4624 bufy.Reset(y);
4625 while (bufx.has_more() && bufy.has_more()) {
4626 int d = bufx.GetNext() - bufy.GetNext();
4627 if (d < 0) return Smi::FromInt(LESS);
4628 else if (d > 0) return Smi::FromInt(GREATER);
4629 }
4630
4631 // x is (non-trivial) prefix of y:
4632 if (bufy.has_more()) return Smi::FromInt(LESS);
4633 // y is prefix of x:
4634 return Smi::FromInt(bufx.has_more() ? GREATER : EQUAL);
4635 } 4847 }
4636 4848
4637 4849
4638 static Object* Runtime_Math_abs(Arguments args) { 4850 static Object* Runtime_Math_abs(Arguments args) {
4639 NoHandleAllocation ha; 4851 NoHandleAllocation ha;
4640 ASSERT(args.length() == 1); 4852 ASSERT(args.length() == 1);
4641 Counters::math_abs.Increment(); 4853 Counters::math_abs.Increment();
4642 4854
4643 CONVERT_DOUBLE_CHECKED(x, args[0]); 4855 CONVERT_DOUBLE_CHECKED(x, args[0]);
4644 return Heap::AllocateHeapNumber(fabs(x)); 4856 return Heap::AllocateHeapNumber(fabs(x));
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
4811 5023
4812 if (y == 0) { 5024 if (y == 0) {
4813 return Smi::FromInt(1); 5025 return Smi::FromInt(1);
4814 } else if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) { 5026 } else if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) {
4815 return Heap::nan_value(); 5027 return Heap::nan_value();
4816 } else { 5028 } else {
4817 return Heap::AllocateHeapNumber(pow(x, y)); 5029 return Heap::AllocateHeapNumber(pow(x, y));
4818 } 5030 }
4819 } 5031 }
4820 5032
5033 // Fast version of Math.pow if we know that y is not an integer and
5034 // y is not -0.5 or 0.5. Used as slowcase from codegen.
5035 static Object* Runtime_Math_pow_cfunction(Arguments args) {
5036 NoHandleAllocation ha;
5037 ASSERT(args.length() == 2);
5038 CONVERT_DOUBLE_CHECKED(x, args[0]);
5039 CONVERT_DOUBLE_CHECKED(y, args[1]);
5040 if (y == 0) {
5041 return Smi::FromInt(1);
5042 } else if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) {
5043 return Heap::nan_value();
5044 } else {
5045 return Heap::AllocateHeapNumber(pow(x, y));
5046 }
5047 }
5048
4821 5049
4822 static Object* Runtime_Math_round(Arguments args) { 5050 static Object* Runtime_Math_round(Arguments args) {
4823 NoHandleAllocation ha; 5051 NoHandleAllocation ha;
4824 ASSERT(args.length() == 1); 5052 ASSERT(args.length() == 1);
4825 Counters::math_round.Increment(); 5053 Counters::math_round.Increment();
4826 5054
4827 CONVERT_DOUBLE_CHECKED(x, args[0]); 5055 CONVERT_DOUBLE_CHECKED(x, args[0]);
4828 if (signbit(x) && x >= -0.5) return Heap::minus_zero_value(); 5056 if (signbit(x) && x >= -0.5) return Heap::minus_zero_value();
4829 double integer = ceil(x); 5057 double integer = ceil(x);
4830 if (integer - x > 0.5) { integer -= 1.0; } 5058 if (integer - x > 0.5) { integer -= 1.0; }
(...skipping 24 matching lines...) Expand all
4855 static Object* Runtime_Math_tan(Arguments args) { 5083 static Object* Runtime_Math_tan(Arguments args) {
4856 NoHandleAllocation ha; 5084 NoHandleAllocation ha;
4857 ASSERT(args.length() == 1); 5085 ASSERT(args.length() == 1);
4858 Counters::math_tan.Increment(); 5086 Counters::math_tan.Increment();
4859 5087
4860 CONVERT_DOUBLE_CHECKED(x, args[0]); 5088 CONVERT_DOUBLE_CHECKED(x, args[0]);
4861 return TranscendentalCache::Get(TranscendentalCache::TAN, x); 5089 return TranscendentalCache::Get(TranscendentalCache::TAN, x);
4862 } 5090 }
4863 5091
4864 5092
5093 static Object* Runtime_DateMakeDay(Arguments args) {
5094 NoHandleAllocation ha;
5095 ASSERT(args.length() == 3);
5096
5097 CONVERT_SMI_CHECKED(year, args[0]);
5098 CONVERT_SMI_CHECKED(month, args[1]);
5099 CONVERT_SMI_CHECKED(date, args[2]);
5100
5101 static const int day_from_month[] = {0, 31, 59, 90, 120, 151,
5102 181, 212, 243, 273, 304, 334};
5103 static const int day_from_month_leap[] = {0, 31, 60, 91, 121, 152,
5104 182, 213, 244, 274, 305, 335};
5105
5106 year += month / 12;
5107 month %= 12;
5108 if (month < 0) {
5109 year--;
5110 month += 12;
5111 }
5112
5113 ASSERT(month >= 0);
5114 ASSERT(month < 12);
5115
5116 // year_delta is an arbitrary number such that:
5117 // a) year_delta = -1 (mod 400)
5118 // b) year + year_delta > 0 for years in the range defined by
5119 // ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of
5120 // Jan 1 1970. This is required so that we don't run into integer
5121 // division of negative numbers.
5122 // c) there shouldn't be overflow for 32-bit integers in the following
5123 // operations.
5124 static const int year_delta = 399999;
5125 static const int base_day = 365 * (1970 + year_delta) +
5126 (1970 + year_delta) / 4 -
5127 (1970 + year_delta) / 100 +
5128 (1970 + year_delta) / 400;
5129
5130 int year1 = year + year_delta;
5131 int day_from_year = 365 * year1 +
5132 year1 / 4 -
5133 year1 / 100 +
5134 year1 / 400 -
5135 base_day;
5136
5137 if (year % 4 || (year % 100 == 0 && year % 400 != 0)) {
5138 return Smi::FromInt(day_from_year + day_from_month[month] + date - 1);
5139 }
5140
5141 return Smi::FromInt(day_from_year + day_from_month_leap[month] + date - 1);
5142 }
5143
5144
4865 static Object* Runtime_NewArgumentsFast(Arguments args) { 5145 static Object* Runtime_NewArgumentsFast(Arguments args) {
4866 NoHandleAllocation ha; 5146 NoHandleAllocation ha;
4867 ASSERT(args.length() == 3); 5147 ASSERT(args.length() == 3);
4868 5148
4869 JSFunction* callee = JSFunction::cast(args[0]); 5149 JSFunction* callee = JSFunction::cast(args[0]);
4870 Object** parameters = reinterpret_cast<Object**>(args[1]); 5150 Object** parameters = reinterpret_cast<Object**>(args[1]);
4871 const int length = Smi::cast(args[2])->value(); 5151 const int length = Smi::cast(args[2])->value();
4872 5152
4873 Object* result = Heap::AllocateArgumentsObject(callee, length); 5153 Object* result = Heap::AllocateArgumentsObject(callee, length);
4874 if (result->IsFailure()) return result; 5154 if (result->IsFailure()) return result;
(...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after
5456 // and print some interesting cpu debugging info. 5736 // and print some interesting cpu debugging info.
5457 JavaScriptFrameIterator it; 5737 JavaScriptFrameIterator it;
5458 JavaScriptFrame* frame = it.frame(); 5738 JavaScriptFrame* frame = it.frame();
5459 PrintF("fp = %p, sp = %p, caller_sp = %p: ", 5739 PrintF("fp = %p, sp = %p, caller_sp = %p: ",
5460 frame->fp(), frame->sp(), frame->caller_sp()); 5740 frame->fp(), frame->sp(), frame->caller_sp());
5461 } else { 5741 } else {
5462 PrintF("DebugPrint: "); 5742 PrintF("DebugPrint: ");
5463 } 5743 }
5464 args[0]->Print(); 5744 args[0]->Print();
5465 if (args[0]->IsHeapObject()) { 5745 if (args[0]->IsHeapObject()) {
5746 PrintF("\n");
5466 HeapObject::cast(args[0])->map()->Print(); 5747 HeapObject::cast(args[0])->map()->Print();
5467 } 5748 }
5468 #else 5749 #else
5469 // ShortPrint is available in release mode. Print is not. 5750 // ShortPrint is available in release mode. Print is not.
5470 args[0]->ShortPrint(); 5751 args[0]->ShortPrint();
5471 #endif 5752 #endif
5472 PrintF("\n"); 5753 PrintF("\n");
5473 Flush(); 5754 Flush();
5474 5755
5475 return args[0]; // return TOS 5756 return args[0]; // return TOS
(...skipping 2528 matching lines...) Expand 10 before | Expand all | Expand 10 after
8004 8285
8005 8286
8006 static Object* Runtime_FunctionGetInferredName(Arguments args) { 8287 static Object* Runtime_FunctionGetInferredName(Arguments args) {
8007 NoHandleAllocation ha; 8288 NoHandleAllocation ha;
8008 ASSERT(args.length() == 1); 8289 ASSERT(args.length() == 1);
8009 8290
8010 CONVERT_CHECKED(JSFunction, f, args[0]); 8291 CONVERT_CHECKED(JSFunction, f, args[0]);
8011 return f->shared()->inferred_name(); 8292 return f->shared()->inferred_name();
8012 } 8293 }
8013 8294
8295
8296 static int FindSharedFunctionInfosForScript(Script* script,
8297 FixedArray* buffer) {
8298 AssertNoAllocation no_allocations;
8299
8300 int counter = 0;
8301 int buffer_size = buffer->length();
8302 HeapIterator iterator;
8303 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
8304 ASSERT(obj != NULL);
8305 if (!obj->IsSharedFunctionInfo()) {
8306 continue;
8307 }
8308 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
8309 if (shared->script() != script) {
8310 continue;
8311 }
8312 if (counter < buffer_size) {
8313 buffer->set(counter, shared);
8314 }
8315 counter++;
8316 }
8317 return counter;
8318 }
8319
8320 // For a script finds all SharedFunctionInfo's in the heap that points
8321 // to this script. Returns JSArray of SharedFunctionInfo wrapped
8322 // in OpaqueReferences.
8323 static Object* Runtime_LiveEditFindSharedFunctionInfosForScript(
8324 Arguments args) {
8325 ASSERT(args.length() == 1);
8326 HandleScope scope;
8327 CONVERT_CHECKED(JSValue, script_value, args[0]);
8328
8329 Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
8330
8331 const int kBufferSize = 32;
8332
8333 Handle<FixedArray> array;
8334 array = Factory::NewFixedArray(kBufferSize);
8335 int number = FindSharedFunctionInfosForScript(*script, *array);
8336 if (number > kBufferSize) {
8337 array = Factory::NewFixedArray(number);
8338 FindSharedFunctionInfosForScript(*script, *array);
8339 }
8340
8341 Handle<JSArray> result = Factory::NewJSArrayWithElements(array);
8342 result->set_length(Smi::FromInt(number));
8343
8344 LiveEdit::WrapSharedFunctionInfos(result);
8345
8346 return *result;
8347 }
8348
8349 // For a script calculates compilation information about all its functions.
8350 // The script source is explicitly specified by the second argument.
8351 // The source of the actual script is not used, however it is important that
8352 // all generated code keeps references to this particular instance of script.
8353 // Returns a JSArray of compilation infos. The array is ordered so that
8354 // each function with all its descendant is always stored in a continues range
8355 // with the function itself going first. The root function is a script function.
8356 static Object* Runtime_LiveEditGatherCompileInfo(Arguments args) {
8357 ASSERT(args.length() == 2);
8358 HandleScope scope;
8359 CONVERT_CHECKED(JSValue, script, args[0]);
8360 CONVERT_ARG_CHECKED(String, source, 1);
8361 Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
8362
8363 JSArray* result = LiveEdit::GatherCompileInfo(script_handle, source);
8364
8365 if (Top::has_pending_exception()) {
8366 return Failure::Exception();
8367 }
8368
8369 return result;
8370 }
8371
8372 // Changes the source of the script to a new_source and creates a new
8373 // script representing the old version of the script source.
8374 static Object* Runtime_LiveEditReplaceScript(Arguments args) {
8375 ASSERT(args.length() == 3);
8376 HandleScope scope;
8377 CONVERT_CHECKED(JSValue, original_script_value, args[0]);
8378 CONVERT_ARG_CHECKED(String, new_source, 1);
8379 CONVERT_ARG_CHECKED(String, old_script_name, 2);
8380 Handle<Script> original_script =
8381 Handle<Script>(Script::cast(original_script_value->value()));
8382
8383 Handle<String> original_source(String::cast(original_script->source()));
8384
8385 original_script->set_source(*new_source);
8386 Handle<Script> old_script = Factory::NewScript(original_source);
8387 old_script->set_name(*old_script_name);
8388 old_script->set_line_offset(original_script->line_offset());
8389 old_script->set_column_offset(original_script->column_offset());
8390 old_script->set_data(original_script->data());
8391 old_script->set_type(original_script->type());
8392 old_script->set_context_data(original_script->context_data());
8393 old_script->set_compilation_type(original_script->compilation_type());
8394 old_script->set_eval_from_shared(original_script->eval_from_shared());
8395 old_script->set_eval_from_instructions_offset(
8396 original_script->eval_from_instructions_offset());
8397
8398
8399 Debugger::OnAfterCompile(old_script, Debugger::SEND_WHEN_DEBUGGING);
8400
8401 return *(GetScriptWrapper(old_script));
8402 }
8403
8404 // Replaces code of SharedFunctionInfo with a new one.
8405 static Object* Runtime_LiveEditReplaceFunctionCode(Arguments args) {
8406 ASSERT(args.length() == 2);
8407 HandleScope scope;
8408 CONVERT_ARG_CHECKED(JSArray, new_compile_info, 0);
8409 CONVERT_ARG_CHECKED(JSArray, shared_info, 1);
8410
8411 LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info);
8412
8413 return Heap::undefined_value();
8414 }
8415
8416 // Connects SharedFunctionInfo to another script.
8417 static Object* Runtime_LiveEditRelinkFunctionToScript(Arguments args) {
8418 ASSERT(args.length() == 2);
8419 HandleScope scope;
8420 CONVERT_ARG_CHECKED(JSArray, shared_info_array, 0);
8421 CONVERT_ARG_CHECKED(JSValue, script_value, 1);
8422 Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
8423
8424 LiveEdit::RelinkFunctionToScript(shared_info_array, script);
8425
8426 return Heap::undefined_value();
8427 }
8428
8429 // Updates positions of a shared function info (first parameter) according
8430 // to script source change. Text change is described in second parameter as
8431 // array of groups of 3 numbers:
8432 // (change_begin, change_end, change_end_new_position).
8433 // Each group describes a change in text; groups are sorted by change_begin.
8434 static Object* Runtime_LiveEditPatchFunctionPositions(Arguments args) {
8435 ASSERT(args.length() == 2);
8436 HandleScope scope;
8437 CONVERT_ARG_CHECKED(JSArray, shared_array, 0);
8438 CONVERT_ARG_CHECKED(JSArray, position_change_array, 1);
8439
8440 LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
8441
8442 return Heap::undefined_value();
8443 }
8444
8445
8446 static LiveEdit::FunctionPatchabilityStatus FindFunctionCodeOnStacks(
8447 Handle<SharedFunctionInfo> shared) {
8448 // TODO(635): check all threads, not only the current one.
8449 for (StackFrameIterator it; !it.done(); it.Advance()) {
8450 StackFrame* frame = it.frame();
8451 if (frame->code() == shared->code()) {
8452 return LiveEdit::FUNCTION_BLOCKED_ON_STACK;
8453 }
8454 }
8455 return LiveEdit::FUNCTION_AVAILABLE_FOR_PATCH;
8456 }
8457
8458 // For array of SharedFunctionInfo's (each wrapped in JSValue)
8459 // checks that none of them have activations on stacks (of any thread).
8460 // Returns array of the same length with corresponding results of
8461 // LiveEdit::FunctionPatchabilityStatus type.
8462 static Object* Runtime_LiveEditCheckStackActivations(Arguments args) {
8463 ASSERT(args.length() == 1);
8464 HandleScope scope;
8465 CONVERT_ARG_CHECKED(JSArray, shared_array, 0);
8466
8467
8468 int len = Smi::cast(shared_array->length())->value();
8469 Handle<JSArray> result = Factory::NewJSArray(len);
8470
8471 for (int i = 0; i < len; i++) {
8472 JSValue* wrapper = JSValue::cast(shared_array->GetElement(i));
8473 Handle<SharedFunctionInfo> shared(
8474 SharedFunctionInfo::cast(wrapper->value()));
8475 LiveEdit::FunctionPatchabilityStatus check_res =
8476 FindFunctionCodeOnStacks(shared);
8477 SetElement(result, i, Handle<Smi>(Smi::FromInt(check_res)));
8478 }
8479
8480 return *result;
8481 }
8482
8483
8014 #endif // ENABLE_DEBUGGER_SUPPORT 8484 #endif // ENABLE_DEBUGGER_SUPPORT
8015 8485
8016 #ifdef ENABLE_LOGGING_AND_PROFILING 8486 #ifdef ENABLE_LOGGING_AND_PROFILING
8017 8487
8018 static Object* Runtime_ProfilerResume(Arguments args) { 8488 static Object* Runtime_ProfilerResume(Arguments args) {
8019 NoHandleAllocation ha; 8489 NoHandleAllocation ha;
8020 ASSERT(args.length() == 2); 8490 ASSERT(args.length() == 2);
8021 8491
8022 CONVERT_CHECKED(Smi, smi_modules, args[0]); 8492 CONVERT_CHECKED(Smi, smi_modules, args[0]);
8023 CONVERT_CHECKED(Smi, smi_tag, args[1]); 8493 CONVERT_CHECKED(Smi, smi_tag, args[1]);
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
8279 } else { 8749 } else {
8280 // Handle last resort GC and make sure to allow future allocations 8750 // Handle last resort GC and make sure to allow future allocations
8281 // to grow the heap without causing GCs (if possible). 8751 // to grow the heap without causing GCs (if possible).
8282 Counters::gc_last_resort_from_js.Increment(); 8752 Counters::gc_last_resort_from_js.Increment();
8283 Heap::CollectAllGarbage(false); 8753 Heap::CollectAllGarbage(false);
8284 } 8754 }
8285 } 8755 }
8286 8756
8287 8757
8288 } } // namespace v8::internal 8758 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/runtime.h ('k') | src/runtime.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698